2023西安邀请赛vp补题

文章目录

  • [H-Spin the Wheel 找规律 模意义下的等差数列](#H-Spin the Wheel 找规律 模意义下的等差数列)
  • [J-Target 位运算](#J-Target 位运算)
  • [I-Square 找规律 贪心 等差数列](#I-Square 找规律 贪心 等差数列)
  • [A Alice and Bob 组合计数 构造?](#A Alice and Bob 组合计数 构造?)

H-Spin the Wheel 找规律 模意义下的等差数列

打表找规律

  • 先转不同位置 再加一次 发现n为奇数 只影响位置
  • 加多次0 1 2 ...n-1 发现加n次又回来了
  • 如果最后一次加的时候 加的数向左移位一下 其实相当于所有数都+1)%n
  • 若a+b=n 在%n的情况下 +a和-b是相同的
  • 所以对0 1 2 3 4 的圈,顺时针转要么+1 要么-(n-1),都相当于+1
  • 观察表,发现相邻的数差的值一样,每次加外圈的数相当于相邻数之间差值+1
  • 所以,判断所给序列是否存在的标准:相邻两个数的差是否一样
  • 如果数列中所有数都相同,说明add了n次,被%n约掉了
  • 结果计算:
    • 相邻数的差=operation 2(add)的次数
    • operation 1(spin)
      • 0+0=0 如果不转,样例中数列第一个数必是0
      • 第一个数不是0,需要转一下,相当于所有数上都加一个数,把第一个数加成目标数
cpp 复制代码
void solve()
{
	int n;
	cin >> n;
	vector<int> a(n + 1);
	forr(i, 0, n - 1) cin >> a[i];
	int dis = (a[0] - a[n - 1] + n) % n;
	forr(i, 1, n - 1) // 模意义下的等差数列
	{
		if ((a[i] - a[i - 1] + n) % n != dis)
			return cout << -1 << endl, void();
	}
	if (dis == 0)
	{
		if (a[0] != 0) // 需要中间变动一下 得到非零相等
			cout << n + 1 << endl;
		else
			cout << 0 << endl;
	}
	else
	{
		cout << dis + (a[0] != 0) << endl;
	}
}

不能只看样例n为奇数,要多打表,把规律找全面。

J-Target 位运算

题意

  • 每次操作要么 ÷ 2 \div2 ÷2,要么 ÷ 2 \div 2 ÷2再 + 0.5 +0.5 +0.5
  • 找 a → b a\rightarrow b a→b的方法,题目中只限制操作次数在50次之内,没有最小操作次数的要求
  • 题中认为 ∣ x − y ∣ ≤ 10 − 4 → x = y |x-y|\leq10^{-4}\rightarrow x=y ∣x−y∣≤10−4→x=y
  • 0 ≤ a ≤ 1 , 0 ≤ b ≤ 1 0\leq a\leq 1,0\leq b\leq 1 0≤a≤1,0≤b≤1

思路

  • a → 0 → b a\rightarrow 0\rightarrow b a→0→b
  • a → 0 a\rightarrow 0 a→0:因为 1 2 15 ≤ 10 − 4 {1\over 2^{15}}\leq 10^{-4} 2151≤10−4,进行15次操作1,一定能把a变成0
  • 0 → b 0\rightarrow b 0→b:
    • 0.5 0.5 0.5的二进制是 0.1 0.1 0.1, 0.75 = 0.5 ÷ 2 + 0.5 0.75=0.5\div2+0.5 0.75=0.5÷2+0.5是 0.11 0.11 0.11
    • ÷ 2 \div2 ÷2相当于1向后移, + 0.5 +0.5 +0.5相当于在第一位放1
    • 将b化二进制,有1的地方说明执行了操作2
    • 同上,找15位就可以
cpp 复制代码
void solve(){
    double a,b;
    cin>>a>>b;
    string ans1,ans2;
    forr(i,1,15)ans1+='1';
    forr(i,1,15){
        b*=2;
        if(b>=1.0){
            ans2+='2';
            b=b-1;
        }else ans2+='1';
    }
    reverse(ans2.begin(),ans2.end());//因为二进制是顺序找的,在前面的1应该在后面放,所以要逆转一下

    cout<<ans1<<ans2;
}

I-Square 找规律 贪心 等差数列

  • x − 1 x-1 x−1让数字变小,如果x>y,直接一步步变小
  • x + ⌊ 2 x + 1.5 ⌋ x + \lfloor \sqrt{2x}+1.5\rfloor x+⌊2x +1.5⌋变大
    • 1 → 1 + 2 = 3 → 3 + 3 = 6 → 6 + 4 = 10 → 10 + 5 → . . . 1\rightarrow1+2=3\rightarrow3+3=6\rightarrow6+4=10\rightarrow10+5\rightarrow... 1→1+2=3→3+3=6→6+4=10→10+5→...
    • 发现每次加的是差为1的等差数列
    • 多打一下这个式子的递推表(横着看)
      直接放dalao的题解...抽象的数值运算映射到三角形数阵的几何结构上
cpp 复制代码
void solve(){
    int x,y;
    cin>>x>>y;
    if(x>=y)return cout<<x-y<<endl,void();// 全用操作1
    else{
        int lx=sqrt(2*x),ly=sqrt(y*2);
        // 凑出包含x,y的三角形 lx ly是三角形层数 
        while(lx*(lx+1)/2<x)lx++;
        while(ly*(ly+1)/2<y)ly++;
        int ans=ly-lx;//操作2 x跳到与y同层 x向上跳的次数 就是三角形差的层数
        int px=x-lx*(lx-1)/2,py=y-ly*(ly-1)/2;//px py代表x y在本层的位置
        
        // 操作1
        //lx-px是到lx层末尾的长度 因为斜着跳 到末尾的长度不变
        if(lx-px<=ly-py){// 如果x进行操作2跳到y的那一层 x'>=y 进行操作1 减到y
            ans+=(ly-py)-(lx-px);
        }else ans+=(ly-py)+px+1;//x'<y 多跳一层跳到ly+1层 x'和y的距离是(ly-py)+px
        cout<<ans<<endl;
    }
}

A Alice and Bob 组合计数 构造?

先通过小样例摸出谁先得到1谁最后必输

又列样例发现

  • 类似 2 3 4 5 1 / 2 3 5 4 1 B赢
  • 3 2 4 5 1 A赢

谁拿到 p 1... p 1 p_{1...p_1} p1...p1中最小 谁就必输

对1~n每个数 q q q,构造 p 1 = q p_1=q p1=q且 p i > q ( i = 2... p 1 ) p_{i}>q(i={2...p_1}) pi>q(i=2...p1)的序列,即B赢

若 p 1 = q p_1=q p1=q,把 n − q n-q n−q个数放进 q − 1 q-1 q−1个位置,有 ( n − q ) ( n − q − 1 ) . . . q − 1 个相乘 = ( n − q ) ! ( n − q − ( q − 1 ) ) ! = ( n − q ) ! ( n − 2 q + 1 ) ! \underset{q-1个相乘}{(n-q)(n-q-1)...}=\frac{(n-q)!}{(n-q-(q-1))!}=\frac{(n-q)!}{(n-2q+1)!} q−1个相乘(n−q)(n−q−1)...=(n−q−(q−1))!(n−q)!=(n−2q+1)!(n−q)!

cpp 复制代码
const int N = 1e7, M = 1e5;
const double PI = acos(-1), eps = 1e-7;
const long long mod = 998244353, inf = 2e18;
int qpow(int a, int b)
{
	int res = 1;
	while (b)
	{
		if (b & 1)
			(res *= a) %= mod;
		b >>= 1;
		(a *= a) %= mod;
	}
	return res;
}
int inv(int x)
{
	return qpow(x, mod - 2) % mod;
}
int fac[N], ifac[N];
void init()
{
	fac[0] = 0, fac[1] = 1;
	forr(i, 2, N)
	{
		fac[i] = fac[i - 1] * i % mod;
	}
	ifac[N] = inv(fac[N]);
	reforr(i, 1, N - 1)
	{
		ifac[i] = ifac[i + 1] * (i + 1) % mod;
	}
	ifac[0] = 1;
}
void solve()
{
	int n;
	cin >> n;
	if (n == 1)
		return cout << 1 << endl, void();
	int ans = fac[n - 1] % mod;
	forr(i, 2, n)
	{
		if (n - i < i - 1)// i-1个位置放不满 必有<i的数 B输
			break;
		(ans += (fac[n - i] * ifac[n - 2 * i + 1]) % mod * fac[n - i] % mod) %= mod;
	}
	cout << ans << endl;
}
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int _ = 1;
	// cin >> _;
	init();
	while (_--)
	{
		solve();
	}
	return 0;
}
相关推荐
唠玖馆1 小时前
c++ list详解
c++
khalil10201 小时前
代码随想录算法训练营Day-38动态规划06 | 322. 零钱兑换、279.完全平方数、139.单词拆分、多重背包、总结
数据结构·c++·算法·leetcode·动态规划
jimy11 小时前
C语言历史版本和gnu扩展版本
c语言·算法·gnu
shehuiyuelaiyuehao1 小时前
关于算法14,15解决一些问题
算法
探序基因1 小时前
单细胞转录组Seurat去批次-FastMNN算法及大细胞量评测
linux·算法
阿Y加油吧1 小时前
二刷 LeetCode:300. 最长递增子序列 & 152. 乘积最大子数组 复盘笔记
笔记·算法·leetcode
我是大聪明.1 小时前
大模型Tokenizer原理:BPE、WordPiece与子词编码的核心机制深度解析
人工智能·线性代数·算法·机器学习·矩阵
自我意识的多元宇宙1 小时前
数据结构----希尔排序
数据结构·算法·排序算法
6Hzlia1 小时前
Hot 100 刷题计划】 LeetCode 146. LRU 缓存 | C++ 哈希表+双向链表
c++·leetcode·缓存