好久没打 CF 了,最近试着 vp 了几场去年的 Global Round,把题解写在这里。
题目链接
https://codeforces.com/contest/1119
A. Parity
从低次向高次暴力计算。
时间复杂度 \(O(k)\)。
#include <iostream> using namespace std; int a[100005]; int main() { int b,k; cin>>b>>k; for(int i=1;i<=k;i++) cin>>a[i]; int ans=a[k]%2,num=1; for(int i=k-1;i;i--) { num=num*b%2; ans=(ans+num*a[i])%2; } if(ans==1)cout<<"odd"<<endl; else cout<<"even"<<endl; return 0; }
B. Tape
和最小生成树的思想很像。
刚开始我们只用一条胶带,覆盖了所有点。
现在我们可以选择撤掉两点间的胶带,每执行一次操作,用的胶带数增加一条。
贪心从大到小撤胶带即可。
#include <iostream> #include <algorithm> using namespace std; int a[100005],d[100005]; bool cmp(int x,int y) { return x>y; } int main() { ios::sync_with_stdio(false); int n,m,k,ans; cin>>n>>m>>k; for(int i=1;i<=n;i++) cin>>a[i]; ans=a[n]-a[1]+1; for(int i=2;i<=n;i++) d[i-1]=a[i]-a[i-1]-1; sort(d+1,d+n,cmp); for(int i=1;i<k;i++) ans-=d[i]; cout<<ans<<endl; return 0; }
C. Meaningless Operations
设 \(k\) 为满足 \(a \leq 2^k-1\) 的最小整数。我们分两种情况讨论。
- \(a \lt 2^k-1\)
构造 \(b=2^k-a\),此时 \(a \oplus b=2^k-1\),\(a \& b=0\),从而取得最大答案 \(2^k-1\)。
- \(a=2^k-1\)
这时候没法做到 \(a\&b=0\) 了。
注意到这时候一定满足 \(a\oplus b+b=2^k-1\),从而问题变成了求 \(\gcd(a-b,b)\) 的最大值。
事实上这个问题等价于 \(\gcd(a,b)\)。
故 \(b\) 就等于 \(a\) 的最大真因子。
#include <cmath> #include <iostream> using namespace std; int f(int x) { int ans=0; while(x) { x>>=1; ans++; } return ans; } int main() { int t; cin>>t; while(t--) { int x; cin>>x; if(x&(x+1))cout<<(1<<f(x))-1<<endl; else { bool flag=true; for(int i=2;i*i<=x;i++) if(x%i==0) { cout<<x/i<<endl; flag=false; break; } if(flag)cout<<1<<endl; } } return 0; }
E. Magic Stones
神仙结论题。
首先如果 \(c_1 \neq t_1\) 或者 \(c_n \neq t_n\) 那显然不行。
排除了这种情况后,我们来看看一次操作会造成怎样的变化。
设 \(a_i=c_{i+1}-c_i\)。
原来的 \(a_i\) 是这样的:\(a_i=c_{i+1}-c_i\),\(a_{i-1}=c_i-c_{i-1}\)。
现在我们将 \(c_i\) 变成 \(c_{i+1}+c_{i-1}-c_i\),这时候的 \(a_i\) 变成了:\(a_i=(c_{i+1}+c_{i-1}-c_i)-c_{i-1}=c_{i+1}-c_i\),\(a_{i+1}=c_{i+1}-(c_{i+1}+c_{i-1}-c_i)=c_i-c_{i-1}\)。
我们发现两个 \(a_i\) 互换了。
于是问题就变成了:给两个差分数组,每次操作可以将其中一个数组的相邻两个元素互换,问能不能让两个数组相等。
这个就很简单了。
#include <iostream> #include <algorithm> using namespace std; int a[100005],b[100005],c[100005],d[100005]; int main() { int n; cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; for(int i=1;i<=n;i++) cin>>b[i]; if(a[1]!=b[1]||a[n]!=b[n]) { cout<<"No"<<endl; return 0; } for(int i=1;i<n;i++) { c[i]=a[i+1]-a[i]; d[i]=b[i+1]-b[i]; } sort(c+1,c+n); sort(d+1,d+n); for(int i=1;i<n;i++) if(c[i]!=d[i]) { cout<<"No"<<endl; return 0; } cout<<"Yes"<<endl; return 0; }
链接是不是放错了 /yiw
https://codeforces.com/contest/1110