#include<bits/stdc++.h>usingnamespace std;constint maxn =1e5+10;char s[maxn];intmain(){int t;
cin >> t;while(t--){int n;scanf("%d",&n);scanf("%s", s +1);int ans =0x3f3f3f3f;int l =1, r = n;char ch[3];int cnt =0;while(l < r){if(s[l]== s[r]){
l++;
r--;}else{
ch[++cnt]= s[l];
ch[++cnt]= s[r];break;}}for(int i =1; i <=2; i++){char c = ch[i];int l =1, r = n;bool flag =1;int cnt =0;while(l < r){if(s[l]== s[r]){
l++;
r--;}elseif(s[l]== c){
l++;
cnt++;}elseif(s[r]== c){
r--;
cnt++;}else{
flag =0;break;}}if(flag){
ans =min(ans, cnt);}}if(ans ==0x3f3f3f3f)
cout <<-1<< endl;else
cout << ans << endl;}return0;}
D. Vupsen, Pupsen and 0
思路分析:
题目要求的是
∑
i
=
1
n
a
i
×
b
i
=
0
\sum_{i = 1}^n{a_i\times b_i} = 0
∑i=1nai×bi=0,我们可以这样想,我们把两个数两两匹配例如:
a
i
=
5
,
a
i
+
1
=
4
a_i = 5, a_{i+1} = 4
ai=5,ai+1=4 我们就可以令
b
i
=
4
,
b
i
+
1
=
−
5
b_i = 4, b_{i+1} = -5
bi=4,bi+1=−5,依次类推。
那么每次都能两两匹配的话
n
n
n必须是偶数,所以还要讨论
n
n
n为奇数的时候,我们可以直接把前三项取出来,让这三项相加为
0
0
0,那么就有三种情况。
代码
#include<bits/stdc++.h>#definelllonglongusingnamespace std;constint maxn =1e5+10;
ll a[maxn];
ll sum;intmain(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);int t;
cin >> t;while(t--){
sum =0;
ll n;
cin >> n;for(int i =1; i <= n; i++){
cin >> a[i];
sum += a[i];}if(n %2==0){for(int i =1; i <= n; i +=2){
cout << a[i +1]<<' '<<-a[i]<<' ';}
cout << endl;}elseif(n %2==1){//不可能三项加起来都为0,所以保证了有答案//推一下就好了if(a[3]+ a[1]!=0)
cout << a[2]<<' '<<-(a[3]+ a[1])<<' '<< a[2]<<' ';elseif(a[1]+ a[2]!=0){
cout << a[3]<<' '<< a[3]<<' '<<-(a[2]+ a[1])<<' ';}elseif(a[3]+ a[2]!=0){
cout <<-(a[2]+ a[3])<<' '<< a[1]<<' '<< a[1]<<' ';}for(int i =4; i <= n; i +=2){
cout << a[i +1]<<' '<<-a[i]<<' ';}
cout << endl;}}return0;}
F1. Korney Korneevich and XOR (easy version)
思路分析:
考虑dp,dp[i]表示得到i这个数的子序列最后一位(递增子序列)的最小值,具体细节看代码注释。
代码
#include<bits/stdc++.h>usingnamespace std;constint maxn =1e5+10;int dp[1001];int a[maxn];intmain(){int n;
cin >> n;for(int i =1; i <= n; i++){
cin >> a[i];}memset(dp,0x3f3f3f3f,sizeof(dp));//先让dp[i]默认为最大
dp[0]=0;//dp[0] = 0;for(int i =1; i <= n; i++){for(int j =1000; j >=0; j--){//更新一下子序列最后一位的最小值if(dp[j]< a[i]){
dp[j ^ a[i]]=min(dp[j ^ a[i]], a[i]);}//只要子序列最后一位的最小值小于当前这个数就可以状态转移,因为保证子序列是递增的。}}int cnt =0;for(int i =0; i <=1000; i++){if(dp[i]!=0x3f3f3f3f)
cnt++;}
cout << cnt << endl;for(int i =0; i <=1000; i++){if(dp[i]!=0x3f3f3f3f)
cout << i <<' ';}
cout << endl;return0;}
F2. Korney Korneevich and XOR (hard version)
思路分析:
如果这题和上题一样的做法的话会T掉,所以要想一下另外一个算法。
这里的dp值其实就是得到的异或值中的子序列中最后一个值的最先出现的位置。
如果能加入到这个子序列的话,那么这个数必须要是在这个子序列中最后一个值出现的位置之后而且值小于它。
代码
#include<bits/stdc++.h>usingnamespace std;constint maxn =1<<13;int f[maxn];constint N =1e6+7;intmain(){int n;
cin >> n;
vector<int>a(n +1), g[5005];for(int i =1; i <= n; i++){
cin >> a[i];
g[a[i]].emplace_back(i);}for(int i =1; i < maxn; i++){
f[i]= N;}for(int i =1; i <=5000; i++){for(int j =0; j < maxn; j++){auto pos =upper_bound(g[i].begin(), g[i].end(), f[j]);if(pos != g[i].end()){
f[i ^ j]=min((*pos), f[i ^ j]);}}}
vector<int> ans;for(int i =0; i < maxn;++i)if(f[i]!= N)
ans.emplace_back(i);
cout << ans.size()<<'\n';for(auto i : ans)
cout << i <<' ';return0;}