Codeforces Round #750 (Div. 2) A B C D F1
A. Luntik and Concerts
- 思路:因为题目保证了a,b,c的数量至少为1,那么易得a,b,c可以任意组成0~a + b * 2 + c * 3 中的任意一个数字,那么为了使两个舞台的相差时间最短,那么显然判断a + b * 2 + c * 3 的奇偶性即可。
- 参考代码:
#include<bits/stdc++.h>
using namespace std;
#define snow ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using ll=long long ;
int main(){
snow;
int t;
cin>>t;
while(t--){
int a,b,c;
cin>>a>>b>>c;
ll ans=a+b*2+c*3;
if(ans%2==0)cout<<0<<endl;
else cout<<1<<endl;
}
return 0;
}
B. Luntik and Subsequences
- 思路:B题其实模拟一下就很容易找到规律,因为要使他的子序列构成 nearly full,所以我们只要关注子序列中的0和1的数量即可。会容易发现最后的方案数是1的个数乘以2的出现数的次方即可,需要注意方案数最大是2^60次方需要开long long。
- 参考代码
#include<bits/stdc++.h>
using namespace std;
#define snow ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using ll=long long ;
const int N=65;
int a[N];
int main(){
snow;
int t;
cin>>t;
while(t--){
int n;
cin>>n;
int res1=0,res0=0;
for(int i=0;i<n;i++){
cin>>a[i];
if(a[i]==1)res1++;
else if(a[i]==0)res0++;
}
ll ans=res1*pow(2,res0);
cout<<ans<<endl;
}
return 0;
}
C. Grandma Capa Knits a Scarf
- 思路:双指针扫描,最大时间复杂度是26*N,时间复杂度足够。
- 参考代码:
#include<bits/stdc++.h>
using namespace std;
#define snow ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using ll=long long ;
const int N=65;
int a[N];
int main(){
snow;
int t;
cin>>t;
while(t--){
int n;
cin>>n;
string s;
cin>>s;
int ans=n+1;
for(char i='a';i<='z';i++){
int l=0,r=s.size()-1;
int cz=0;
while(l<=r){
if(s[l]==s[r]){
l++,r--;
}
else if(s[l]==i){
l++;
cz++;
}
else if(s[r]==i){
r--;
cz++;
}
else{
cz=n+1;
break;
}
}
ans=min(ans,cz);
}
if(ans==n+1)cout<<-1<<endl;
else cout<<ans<<endl;
}
return 0;
}
D. Vupsen, Pupsen and 0
- 思路:题目要求的是构造一个b数组,使得a[1]b[1] + a[2]b[2]… a[n]*b[n]=0,并且所有的$\left\vert b[1]\right\vert$+…$\left\vert b[n]\right\vert$值要小于等于$10^9$,显然偶数情况下我们只需要进行配对可以分成n/2个组合,例如a[1]和a[2]相对应的b[1]=a[2],b[2]=-a[1] 那么必定能使得最后的和的值为0。如果n是奇数的话,我们只需要将前面三个数进行处理例如 a[1] 和 a[2] 和 a[3] 相对应的 b[1]=a[3],b[2]=a[3] ,b[3]=-(a[1]+a[2]) 并且后面部分按照偶数情况处理那么便可以了,但是需要注意前面选择的三个数字可能会出现 a b c 但a = -b 的情况那么-(a+b)会变成0,显然与题目要求的b数组中不能出现0相悖,再仔细思考会发现我们只需要进行分类讨论前三个数即可,如果a=-b那么c的出现必然会使得三个数中至少其中两个数是正数或是负数,那么我们只需要让那两个正数或者负数为上面情况中的a和b那么-(a+b)必然不会是0,因此这个坑我们也可以巧妙处理了。
- 参考代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N];
#define snow ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int main(){
snow;
int t;
cin>>t;
while(t--){
int n;
cin>>n;
if(n%2==0){
int g=n/2;
while(g--){
int a,b;
cin>>a>>b;
cout<<-b<<' '<<a<<' ';
}
cout<<endl;
}
else if(n%2==1){
int a,b,c;
cin>>a>>b>>c;
if(a==-b){
if(b==c){
cout<<-(b+c)<<' '<<a<<' '<<a<<' ';
}
else if(a==c){
cout<<b<<' '<<-(a+c)<<' '<<b<<' ';
}
else{
cout<<-(b+c)<<' '<<a<<' '<<a<<' ';
}
}
else{
cout<<c<<' '<<c<<' '<<-(a+b)<<endl;
}
n-=3;
int g=n/2;
while(g--){
cin>>a>>b;
cout<<-b<<' '<<a<<' ';
}
cout<<endl;
}
}
return 0;
}
F1.Korney Korneevich and XOR (easy version)
- 思路:题目要求的是从A序列中选取一段上升序列(一开始读假题了),那么限制了可异或的条件,也就是132的话不能选取1 ^ 3 ^ 2的的值。本题n最大是1e5+10,a的值最大是500,熟悉了的话很快就能发现这是一个dp背包问题,并且由于5e7的复杂度尚可接受,本题可直接采取暴力dp背包求解。
- 参考代码+详细注释:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N];
int f[N];//用来表示当前异或值是否可得到,并且保留这个可异或得到的多个上升序列中最后一位最小。
#define snow ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);//加速器
int main(){
snow;
int n;
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];//读入a序列
memset(f,0x3f,sizeof f);//全部初始化为0x3f表示异或值尚不可得
f[0]=0;//打开入口f[0]=0,因为0必定能得到且最小的最后一位必定是0。
for(int i=1;i<=n;i++){
for(int j=0;j<512;j++){//因为a的数值最大是500,在二进制中a所能异或得到的最大值为511
if(f[j]<a[i])f[j^a[i]]=min(f[j^a[i]],a[i]);//为什么f[j]<a[i]才能进行转移呢?这个是本题的核心,因为我们题目
}//要求的是选取一个上升序列,如果a[i]<f[j]则说明当前选取的a[i]比当前尽可能最小的状态表示值f[j]还小,那显然无法
}//形成一个上升序列,与题目不符,当然f[j]<=a[i]也是可以的。min的存在也就是为了使得能到达f[j^a[i]]的最后一个值尽可能
int res=0;//最小,很好理解,如果5^8=13和0^13=13。那么显然前者存的是8,后者存的是13,前者能够有更多机会去更新新的异或值
for(int i=0;i<512;i++){//降低了异或的下限,多了更多的可能。
if(f[i]<512)res++;//统计能够异或得到数量
}
cout<<res<<endl;
for(int i=0;i<512;i++)if(f[i]<512)cout<<i<<' ';//将每个能够异或得到的输出,因为最大不超过511,所以扫一遍就好了。
cout<<endl;
return 0;
}