A. Reverse and Concatenate
题意:给你一个字符串s,可以进行k次操作,每次操作只有两种方案:①:原串+原串的反转②:原串的反转+原串,求k次操作后能得到多少个字符串?
思路:首先观察操作,将原串反转之后和原串拼接起来,那不就变成回文串了吗?反复这么操作最后也还是回文,所以在第二次操作之后就没有意义了,那么观察第一次操作,如果本身就为回文,那么两次操作得到的结果相同。再特判一下不进行操作的时候。
#include<bits/stdc++.h> using namespace std; int main() { string s1; int n,i,j,t,k; // map<string , int >mo; cin>>t; while(t--) { cin>>n>>k; cin>>s1; int f1=0; for(i=0;i<s1.length()/2;i++) { if(s1[i]!=s1[n-1-i]) f1=1; } if(f1==0||k==0) { cout<<1<<endl; } else { cout<<2<<endl; } } return 0; }
B. Fortune Telling
题意:给你一个原数x和经过n次运算后的y,按顺序参与n次运算的另个一数,且运算只有加法和异或两种选择, 保证一定有答案,求最后是原数x能得到y还是x+3能得到y
思路:一开始掉进坑了,还在想异或和加法的关系啥的,但是没注意这个+3,既然保证答案一定存在,且要么为x要么为x+3,再观察异或和加法有什么共同性质呢? 这时候只要你注意到了最后一位的变化就能A了,异或其实就是不进位的加法,那么最后一位是不是永远不会进位,所以单看最后一位发现异或和加法其实是相同的,那么x和x+3看最后一位也就是0和1的区别。
所以就当做异或从头异或到尾,然后判断一下是不是都为0,不是就x+3
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+1000; int a[maxn]; int main() { long long n,i,j,t,y,x; cin>>t; while(t--) { cin>>n>>x>>y; for(i=0;i<n;i++) { cin>>a[i]; x^=a[i]; } x^=y; if(x&1) { cout<<"Bob"<<endl; } else { cout<<"Alice"<<endl; } } return 0; }
C. OKEA
题意:有nk个物品,每个物品价值就是从1~nk,求把他们按照n行k个排完之后,能否满足每行里的任意区间的算数平均值都为整数。
思路:观察如果要任意区间长度的算数平均值都为整数,那么这一行的奇偶性必须相同,不然如果区间长度都取2,如果该区间是 3 5 4 ,那么取后面两个5+4=9就不为偶数了,那如果区间长度取到3呢? 可以观察到等差数列的求和公式中有一种形式是((a1+an)n)/2,首项加末项肯定能被2整除,因为奇偶性相同,然后再乘项数,不就是乘区间长度吗?那么刚好就能被整除了
所以只要1,3,5,7…
2,4,6,8…
这样奇偶性质相同的填下去就行,如果哪行填完之后超出了nK的限制,那么就输出NO,无法构成。
#include<bits/stdc++.h> using namespace std; const int maxn=505; int a[maxn][maxn]; int main() { int n,i,j,t,k; cin>>t; while(t--) { cin>>n>>k; int ji=1,ou=2,f1=0; for(i=0;i<n;i++) { for(j=0;j<k;j++) { if(i%2==0) { a[i][j]=ji; if(ji>n*k) f1=1; ji+=2; } else { a[i][j]=ou; if(ou>n*k) f1=1; ou+=2; } } } if(f1==1) { scNO; } else { scYES; for(i=0;i<n;i++) { for(j=0;j<k;j++) { cout<<a[i][j]<<" "; } cout<<endl; } } } return 0; }