AB
签到(A是a-b problem就不放code了)
#include<bits/stdc++.h> using namespace std; int r,g,b,n,ans; int main() { cin>>r>>g>>b>>n; for(int i=0;i*r<=n;i++) for(int j=0;i*r+j*g<=n;j++) if((n-i*r-j*g)%b==0)ans++; cout<<ans<<endl; }
C
签到,首先把所有字符串内部的AB加上,然后记录3种字符串的个数:仅头是B,仅尾是A,头是B且尾是A,然后把第3种顺次连接,其余加上取个min
#include<bits/stdc++.h> using namespace std; int n,ans,s1,s2,s3; char s[15]; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%s",s+1); int len=strlen(s+1); for(int i=1;i<len;i++)if(s[i]=='A'&&s[i+1]=='B')ans++; if(s[1]=='B'&&s[len]=='A')s3++; else if(s[1]=='B')s1++; else if(s[len]=='A')s2++; } if(s3) { ans+=s3-1; if(s1)s1--,ans++; if(s2)s2--,ans++; } cout<<ans+min(s1,s2)<<endl; }
D
知道n=[n/m]*m+n%m这道题就是签到题了,设[n/m]=n%m=x,然后n=x(m+1),O(√n)枚举因数即可
#include<bits/stdc++.h> using namespace std; typedef long long ll; ll n,ans; void judge(ll m,ll x) { if(!m)return; if(n/m==x&&n%m==x)ans+=m; } int main() { cin>>n; for(ll i=1;i*i<=n;i++) if(n%i==0) { judge(i-1,n/i); if(i*i<n)judge(n/i-1,i); } cout<<ans; }
E
要使每一段异或起来相等,实际上就等价于每一段每一位为1的个数的奇偶性相同。设a[i]为前i个数的异或和。然后如果a[n]!=0,显然只能分成奇数段,然后a[n]为0的位,每一段该位偶数个,a[n]不为0的位,每一段该位奇数个1,然后取断点的值,发现就是a[n] 0 a[n] 0…a[n],然后建两颗线段树,分奇偶讨论一下即可。a[n]=0,可奇可偶,奇数段的话,每一个断点a[i]都要为0,偶数段则是交替x 0 x 0…x 0,然后考虑断开处x=0的情况,可以统计a[i]=0(1<=i<n)的个数x,答案是2x,若x!=0,把x分类,DP一下,遇到0总方案加上前面f[i]的和即可,比较麻烦,细节见code。
#include<bits/stdc++.h> using namespace std; #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 const int N=5e5+7,M=1048600,mod=1e9+7; struct tree{ int sum[N<<2]; void build(int l,int r,int rt) { if(l==r){sum[rt]=(l==0);return;} int mid=l+r>>1; build(lson),build(rson); sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%mod; } void update(int k,int v,int l,int r,int rt) { if(l==r){sum[rt]=v;return;} int mid=l+r>>1; if(k<=mid)update(k,v,lson);else update(k,v,rson); sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%mod; } int query(int L,int R,int l,int r,int rt) { if(L<=l&&r<=R)return sum[rt]; int ret=0,mid=l+r>>1; if(L<=mid)ret=(ret+query(L,R,lson))%mod; if(R>mid)ret=(ret+query(L,R,rson))%mod; return ret; } }tr[2]; int n,ans,psum,tot,a[N],s[20][N],sum[N],pw[N],f[N]; vector<int>G[M]; int main() { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=0;i<20;i++)for(int j=1;j<=n;j++)s[i][j]=(s[i][j-1]+((a[j]>>i)&1))%2; int flag=0; for(int i=0;i<20;i++)if(s[i][n])flag=1; if(!flag) { int n0=1,lst=0; for(int i=1;i<=n;i++)a[i]^=a[i-1]; for(int i=1;i<n;i++) if(!a[i])n0=2ll*n0%mod,sum[i]=sum[i-1]+1;else G[a[i]].push_back(i),sum[i]=sum[i-1]; for(int v=1;v<(1<<20);v++) if(G[v].size()) { int sz=G[v].size(),pre=0; for(int i=0;i<sz;i++)f[i]=0; f[0]=1,ans=(ans+1)%mod; for(int i=1;i<sz;i++) { int s0=sum[G[v][i]-1]-sum[G[v][i-1]]; pre=(pre+1ll*f[i-1]*s0)%mod; ans=(ans+pre+1)%mod; f[i]=(f[i-1]+pre+1)%mod; } } ans=(ans+n0)%mod; printf("%d ",ans); return 0; } tr[0].build(0,n,1); tr[1].build(0,n,1); tr[1].update(0,0,0,n,1); for(int i=1;i<=n;i++) { int s1=0,dif=0,add; for(int j=0;j<20;j++) { if(s[j][i])s1++; if(s[j][i]!=s[j][n])dif++; } if(!s1)add=tr[1].query(0,i-1,0,n,1),tr[0].update(i,add,0,n,1); if(!dif)add=tr[0].query(0,i-1,0,n,1),tr[1].update(i,add,0,n,1); } ans=tr[1].query(n,n,0,n,1); printf("%d ",ans); }
F
只有IOI2017 rank1会做,咕了。
result:rank88 unrated了?