Codeforces Round #682 (Div. 2) 题解(A-E)
题意:构造一个长度为n的数组,使得每个子数组中所有元素的和能被这个子数组的长度整除
解题思路:显然,构造一个元素全部相同的数组即可满足要求
代码:
#include<iostream> #include<algorithm> #include<vector> #include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<set> #include<stack> #include<map> #define pb push_back #define mp make_pair #define fi first #define se second #define mul_mod(a,b,c) a=(a*b)%mod #define add_mod(a,b,c) a=(a+b)%mod using namespace std; typedef long long ll; const int maxn=2e5+10; const int maxm=5e5+10; const int inf=0x3f3f3f3f; int q; int n; int main() { scanf("%d",&q); while(q--){ scanf("%d",&n); for(int i=1;i<=n;i++) cout<<1<<" "; cout<<endl; } return 0; }

题意:给出一个数组b,由数组b可以得到数组a(ai=2^bi,1<=i<=n),问a数组是否存在两个不想交的区间,区间和相等。
解题思路:由于a数组全是二次幂,通过二进制的性质可得,如果a数组都是互不相同的元素,不可能存在两个区间和相等(因为只有存在相同的二次幂才可能向上进位,进而与其他的二次幂相等)。所以只要判断b数组中是否存在一个元素出现两次即可。
代码:
#include<iostream> #include<algorithm> #include<vector> #include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<set> #include<stack> #include<map> #define pb push_back #define mp make_pair #define fi first #define se second #define mul_mod(a,b,c) a=(a*b)%mod #define add_mod(a,b,c) a=(a+b)%mod using namespace std; typedef long long ll; const int maxn=2e5+10; const int maxm=5e5+10; const int inf=0x3f3f3f3f; int q,n; int main() { scanf("%d",&q); while(q--){ scanf("%d",&n); map<int,int> ma; int flag=0; for(int i=1;i<=n;i++){ int t; scanf("%d",&t); if(ma[t]) flag=1; else ma[t]=1; } if(flag) puts("YES"); else puts("NO"); } return 0; }

题意:给出一个n*m的矩阵,问是否能对其中若干元素加1,使得没有两个相邻元素相等。
解题思路:可以通过下图所示的黑白棋盘得到启发,因为奇偶性不同的数字必然不等,可以通过给元素加1来改变元素的奇偶性,将整个矩阵分成奇数和偶数两种(类比于棋盘的黑白两色)

代码:
#include<iostream> #include<algorithm> #include<vector> #include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<set> #include<stack> #include<map> #define pb push_back #define mp make_pair #define fi first #define se second #define mul_mod(a,b,c) a=(a*b)%mod #define add_mod(a,b,c) a=(a+b)%mod using namespace std; typedef long long ll; const int maxn=1e2+10; const int maxm=5e5+10; const int inf=0x3f3f3f3f; int q,n,m,t; int main() { scanf("%d",&q); while(q--){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ scanf("%d",&t); if((i+j)%2==t%2) t++; cout<<t<<" "; } cout<<endl; } } return 0; }

题意:给出一个数组,可以将数组中三个元素的值同时变成三个元素的异或(ai=aj=ak=(ai^aj^ak)。问能否在n步操作内将数组变成全部相等的元素,能的话请给出操作步数以及具体步骤。
解题思路:
通过观察能够发现以下两个特性:
1. ax^ax^ay=ay 即两个相同的元素与第三个元素进行异会得到第三个元素
2. a1^a2^a3=p1 p1^p1^p1=p1 => 操作前后三个元素的异或得到的值不会改变
我们先考虑当n为奇数的情况:
| a1 | a2 | a3 | a4 | a5 | a6 | a7 |
| p1 | p1 | p1 | a4 | a5 | a6 | a7 |
| p1 | p1 | p2 | p2 | p2 | a6 | a7 |
| p1 | p1 | p2 | p2 | p3 | p3 | p3 |
其中: p1=a1^a2^a3 p2=a3^a4^a5 p3=a5^a6^a7
于是可以根据第一个特性分别将两个p1、p2与p3进行异或,使得全部等于p3
同理,所有n为奇数的情况都可以通过上述操作步骤使得数组元素全部相等
我们再来考虑n为偶数的情况:
首先,根据第二个特性可知整个数组的异或和是不会随着操作改变的,而我们又能清楚最终的结果是元素全部相等,再加上n为偶数,可以得到以下结论:
如果存在操作能够使得元素全部相等,那么数组的异或和必为0。
如果不为0,则无论如何都不可能使得数组内全部相等。
所以可以在一开始把全部元素异或一遍,如果不为0,直接输出NO
如果为0,将前面n-1个元素按照n为奇数的处理方式处理一遍,将前面n-1个元素都变成相同的。
由于整体异或和为0,所以此时最后一个元素也和前面n-1个元素相等,即全部元素相等,操作完毕。
代码:
#include<iostream> #include<algorithm> #include<vector> #include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<set> #include<stack> #include<map> #define pb push_back #define mp make_pair #define fi first #define se second #define mul_mod(a,b,c) a=(a*b)%mod #define add_mod(a,b,c) a=(a+b)%mod using namespace std; typedef long long ll; const int maxn=1e5+10; const int maxm=5e5+10; const int inf=0x3f3f3f3f; int n; int a[maxn]; void solveAdd(int n){ puts("YES"); printf("%d\n",n-2); for(int i=1;i<n;i+=2) printf("%d %d %d\n",i,i+1,i+2); for(int i=1;i<n-2;i+=2) printf("%d %d %d\n",i,i+1,n); } void solveEven(int n){ int sum=0; for(int i=1;i<=n;i++) sum^=a[i]; if(sum){ puts("NO"); return; } solveAdd(n-1); } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); if(n%2) solveAdd(n); else solveEven(n); return 0; }

题意:给定一个长度为n(3<=n<=2e5)的数组,问存在多少个长度至少为3区间[l,r],满足a[l]^a[r]=(a[l+1]+a[l+2]+...+a[r-1])
解题思路:通过左右两端点的值来给限定最大值,假设k是a[l]和a[r]中二进制的最高位,则最大值设为1<<(k+1),
很显然a[l]^a[r]< 1<<(k+1)。通过正反遍历两遍,枚举左右端点,遇到满足的就存入set数组,存入set数组是为了避免重复计算。
时间复杂度为什么是O(2*n*log(Maxa[i]))我还是没懂,证明不了,等到啥时候懂了再补上
代码:
#include<iostream> #include<algorithm> #include<vector> #include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<set> #include<stack> #include<map> #define pb push_back #define mp make_pair #define fi first #define se second #define mul_mod(a,b,c) a=(a*b)%mod #define add_mod(a,b,c) a=(a+b)%mod using namespace std; typedef long long ll; const int maxn=2e5+10; const int maxm=5e5+10; const int inf=0x3f3f3f3f; int n; int a[maxn]; set<ll> se; int getMax(int x){ for(int i=1<<30;i;i>>=1){ if(x&i) return i<<1; } } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int l=1;l<n-1;l++){ ll sum=a[l+1]; int k=getMax(a[l]); for(int r=l+2;r<=n&&sum<=k;r++){ if((a[l]^a[r])==sum) se.insert((ll)l*maxn+r); sum+=a[r]; } } for(int r=n;r>=3;r--){ ll sum=a[r-1]; int k=getMax(a[r]); for(int l=r-2;l>=1&&sum<=k;l--){ if((a[l]^a[r])==sum) se.insert((ll)l*maxn+r); sum+=a[l]; } } cout<<se.size()<<endl; return 0; }

浙公网安备 33010602011771号