没有找到这场div3被改成div2的理由。
A:签到。
#include<bits/stdc++.h> using namespace std; #define ll long long #define inf 1000000010 char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int a[3],d; signed main() { cin>>a[0]>>a[1]>>a[2]>>d; sort(a,a+3); cout<<max(0,d-(a[1]-a[0]))+max(0,d-(a[2]-a[1])); return 0; //NOTICE LONG LONG!!!!! }
B:随便做?
#include<bits/stdc++.h> using namespace std; #define ll long long #define inf 1000000010 #define N 1000010 char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int T; char a[N],b[N]; signed main() { T=read(); while (T--) { scanf("%s",a+1);int n=strlen(a+1); scanf("%s",b+1);int m=strlen(b+1); int cur=0;bool flag=1; for (int i=1;i<=n;i++) if (i==n) { if (cur==m) {flag=0;break;} for (int j=cur+1;j<=m;j++) if (a[i]!=b[j]) {flag=0;break;} } else if (a[i]==a[i+1]) { if (cur==m||a[i]!=b[cur+1]) {flag=0;break;} else cur++; } else { if (cur==m||b[cur+1]!=a[i]) {flag=0;break;} cur++;int tmp=cur; while (cur<m&&b[cur+1]==b[tmp]) cur++; } if (flag) printf("YES "); else printf("NO "); } return 0; //NOTICE LONG LONG!!!!! }
C:显然应该先删权值大的。注意到值域只有100,于是记录每个权值出现次数从大到小删直到满足条件即可。
#include<bits/stdc++.h> using namespace std; #define ll long long #define inf 1000000010 #define N 200010 char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,m,a[N],cnt[N]; signed main() { n=read(),m=read(); for (int i=1;i<=n;i++) a[i]=read(); int s=0; for (int i=1;i<=n;i++) { int u=m-a[i],c=0,w=s; if (s>u) for (int j=100;j>=1;j--) if (w-cnt[j]*j>u) c+=cnt[j],w-=cnt[j]*j; else {c+=(w-u-1)/j+1;break;} cnt[a[i]]++;s+=a[i]; printf("%d ",c); } return 0; //NOTICE LONG LONG!!!!! }
D:判一下删第一个数或删第二个数可不可行。不行的话公差就被固定下来,直接check。
#include<bits/stdc++.h> using namespace std; #define ll long long #define inf 2000000010 #define N 200010 char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n; struct data { int x,i; bool operator <(const data&a) const { return x<a.x; } }a[N]; int check(int l,int r) { int d=a[l+1].x-a[l].x; for (int i=l+2;i<=r;i++) if (a[i].x-a[i-1].x!=d) return inf; return d; } signed main() { n=read(); for (int i=1;i<=n;i++) a[i].x=read(),a[i].i=i; sort(a+1,a+n+1); if (n==2||n==3) {cout<<1;return 0;} if (check(2,n)!=inf) {cout<<a[1].i;return 0;} if (check(3,n)==a[3].x-a[1].x) {cout<<a[2].i;return 0;} int d=a[2].x-a[1].x; bool flag=0;int ans=0,last=a[2].x; for (int i=3;i<=n;i++) if (a[i].x-last!=d) { if (flag) {cout<<-1;return 0;} else flag=1,ans=a[i].i; } else last=a[i].x; cout<<ans; return 0; //NOTICE LONG LONG!!!!! }
E:找到每种字母最左上和最右下出现位置。然后依次覆盖并check。注意细节。
#include<bits/stdc++.h> using namespace std; #define ll long long #define inf 2000000010 #define N 2010 char getc(){char c=getchar();while ((c!='.')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int T,n,m,c,first[30][2],last[30][2]; char a[N][N],b[N][N]; signed main() { T=read(); while (T--) { n=read(),m=read();c=0; memset(first,0,sizeof(first)); memset(last,0,sizeof(last)); for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) { a[i][j]=getc(); if (a[i][j]!='.') { c=max(c,a[i][j]-'a'+1); if (!first[a[i][j]-'a'+1][0]) first[a[i][j]-'a'+1][0]=i,first[a[i][j]-'a'+1][1]=j; last[a[i][j]-'a'+1][0]=i,last[a[i][j]-'a'+1][1]=j; } } bool flag=1; for (int i=1;i<=c;i++) if (first[i][0]!=last[i][0]&&first[i][1]!=last[i][1]) {flag=0;break;} if (!flag) printf("NO "); else { for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) b[i][j]='.'; for (int i=1;i<=c;i++) if (first[i][0]) if (first[i][0]==last[i][0]) for (int j=first[i][1];j<=last[i][1];j++) b[first[i][0]][j]='a'+i-1; else for (int j=first[i][0];j<=last[i][0];j++) b[j][first[i][1]]='a'+i-1; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) if (a[i][j]!=b[i][j]) {flag=0;break;} if (!flag) printf("NO "); else { printf("YES "); printf("%d ",c); for (int i=1;i<=c;i++) if (first[i][0]) { printf("%d %d %d %d ",first[i][0],first[i][1],last[i][0],last[i][1]); } else printf("%d %d %d %d ",first[c][0],first[c][1],last[c][0],last[c][1]); } } } return 0; //NOTICE LONG LONG!!!!! }
F:将每个数字是否出现视为9位二进制数。暴力枚举选择哪两个二进制数。注意细节。
#include<bits/stdc++.h> using namespace std; #define ll long long #define inf 2000000010 #define N 100010 char getc(){char c=getchar();while ((c!='.')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,m,a[N],b[N],c[N],f[1<<9],g[1<<9],id[1<<9]; signed main() { n=read(),m=read(); for (int i=1;i<=n;i++) { int x=read(); for (int j=1;j<=x;j++) a[i]|=1<<read()-1; } for (int i=1;i<=m;i++) { c[i]=read();int x=read(); for (int j=1;j<=x;j++) b[i]|=1<<read()-1; } for (int i=1;i<=n;i++) g[a[i]]++; for (int i=1;i<(1<<9);i++) for (int j=i;j;j=j-1&i) f[i]+=g[j]; memset(g,60,sizeof(g)); for (int i=1;i<=m;i++) if (c[i]<g[b[i]]) { g[b[i]]=c[i]; id[b[i]]=i; } int mx=0,mn=inf*2,ansx=0,ansy=0; for (int i=1;i<(1<<9);i++) for (int j=1;j<(1<<9);j++) if (id[i]&&id[j]&&f[i|j]>=mx) { if (f[i|j]>mx||f[i|j]==mx&&g[i]+g[j]<mn) mx=f[i|j],ansx=id[i],ansy=id[j],mn=g[i]+g[j]; } if (ansx!=ansy) cout<<ansx<<' '<<ansy; else { if (ansx==0) { int mn=inf,mn2=inf,id1,id2; for (int i=1;i<=m;i++) if (c[i]<mn) mn2=mn,mn=c[i],id2=id1,id1=i; else if (c[i]<mn2) mn2=c[i],id2=i; cout<<id1<<' '<<id2<<endl; } else { int cost=inf,id; for (int i=1;i<=m;i++) if (i!=ansx&&c[i]<cost) cost=c[i],id=i; cout<<ansx<<' '<<id; } } return 0; //NOTICE LONG LONG!!!!! }
G:G1随手状压dp。
#include<bits/stdc++.h> using namespace std; #define ll long long #define inf 2000000010 #define N 250 #define P 1000000007 char getc(){char c=getchar();while ((c!='.')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,T,f[1<<15][3],s[1<<15],lg2[1<<15]; struct data{int x,y; }a[N]; void inc(int &x,int y){x+=y;if (x>=P) x-=P;} signed main() { n=read(),T=read(); for (int i=0;i<n;i++) a[i].x=read(),a[i].y=read()-1; for (int i=0;i<n;i++) f[1<<i][a[i].y]=1; for (int i=1;i<(1<<n);i++) for (int j=0;j<3;j++) for (int x=0;x<n;x++) if (i&(1<<x)&&a[x].y==j) { for (int k=0;k<3;k++) if (j!=k) inc(f[i][j],f[i^(1<<x)][k]); } for (int i=0;i<n;i++) lg2[1<<i]=i; for (int i=1;i<(1<<n);i++) s[i]=s[i^(i&-i)]+a[lg2[i&-i]].x; int ans=0; for (int i=1;i<(1<<n);i++) if (s[i]==T) inc(ans,f[i][0]),inc(ans,f[i][1]),inc(ans,f[i][2]); cout<<ans; return 0; //NOTICE LONG LONG!!!!! }
G2首先容易想到只要求出f[x][y][z]为选择三类物品各x,y,z个且总重量和为T的方案数,将其排列的方案数可以随后计算。直接暴力背包复杂度O(Tn4),常数应该非常小空间搞搞应该也没问题大概就能过了,但看起来复杂度有点垃圾。而优化非常简单,可以把前两类物品先放一块做O(Tn3)的背包,然后再对第三类物品自身做背包,最后合并两个背包,由于总重量和T固定,复杂度即为O(Tn3)。
#include<bits/stdc++.h> using namespace std; #define ll long long #define inf 2000000010 #define N 55 #define M 2550 #define P 1000000007 char getc(){char c=getchar();while ((c!='.')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,m,f[N][N][N][3],g[N][N][N],h[M][N][N],u[M][N],fac[N],ans; struct data { int x,y; bool operator <(const data&a) const { return y<a.y; } }a[N]; void inc(int &x,int y){x+=y;if (x>=P) x-=P;} signed main() { n=read(),m=read(); for (int i=1;i<=n;i++) a[i].x=read(),a[i].y=read(); sort(a+1,a+n+1); f[1][0][0][0]=f[0][1][0][1]=f[0][0][1][2]=1; for (int i=2;i<=n;i++) for (int x=0;x<=i;x++) for (int y=0;x+y<=i;y++) { int z=i-x-y; if (x) { inc(f[x][y][z][0],f[x-1][y][z][1]); inc(f[x][y][z][0],f[x-1][y][z][2]); } if (y) { inc(f[x][y][z][1],f[x][y-1][z][0]); inc(f[x][y][z][1],f[x][y-1][z][2]); } if (z) { inc(f[x][y][z][2],f[x][y][z-1][0]); inc(f[x][y][z][2],f[x][y][z-1][1]); } } for (int i=0;i<=n;i++) for (int j=0;j<=n;j++) for (int k=0;k<=n;k++) g[i][j][k]=((f[i][j][k][0]+f[i][j][k][1])%P+f[i][j][k][2])%P; fac[0]=1;for (int i=1;i<=n;i++) fac[i]=1ll*fac[i-1]*i%P; for (int i=0;i<=n;i++) for (int j=0;j<=n;j++) for (int k=0;k<=n;k++) g[i][j][k]=1ll*g[i][j][k]*fac[i]%P*fac[j]%P*fac[k]%P; int t=n; for (int i=n;i>=1;i--) if (a[i].y!=3) {t=i;break;} h[0][0][0]=1; for (int i=1;i<=t;i++) for (int j=i*50;j>=a[i].x;j--) for (int x=0;x<=i;x++) for (int y=0;y<=i;y++) if (a[i].y==1) { if (x) inc(h[j][x][y],h[j-a[i].x][x-1][y]); } else { if (y) inc(h[j][x][y],h[j-a[i].x][x][y-1]); } u[0][0]=1; for (int i=t+1;i<=n;i++) for (int j=m;j>=a[i].x;j--) for (int k=1;k<=n;k++) inc(u[j][k],u[j-a[i].x][k-1]); for (int i=0;i<=m;i++) for (int x=0;x<=n;x++) for (int y=0;y<=n;y++) if (h[i][x][y]) for (int z=0;z<=n;z++) inc(ans,1ll*h[i][x][y]*u[m-i][z]%P*g[x][y][z]%P); cout<<ans; return 0; //NOTICE LONG LONG!!!!! }
小小小小小号小号5。结束时是official的rk3,st完变成rk1,可能因为cf有一些新的规定于是被ban成unofficial的了,感觉有点惨。