B. Email from Polycarp
题意:给定一个原串 一个输出串 因为键盘问题 按键按一下可能出现多个 判断原创和输出串是否匹配
如 hello 和 heellooooooo 是匹配的
指针扫一遍即可 优先级 原串大于last
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m) #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s); #define ll long long #define pb push_back #define inf 0x3f3f3f3f #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// const int N=1e6+6; char s1[N],s2[N]; int main() { int cas;RI(cas); while(cas--) { RS(s1);RS(s2); if(strlen(s1)>strlen(s2)){puts("NO");continue;} int last=-1; int lena=strlen(s1); int lenb=strlen(s2); int L=0; int ok=0; rep(i,0,lenb-1) { if(s2[i]==s1[L]&&L<lena) { L++;last=s2[i];continue; } else if( s2[i]==last ) { continue; } else {L=0;break;} } if(L==lena)puts("YES"); else puts("NO"); } return 0; }
C2. Exam in BerSU (hard version)
有n个物品 背包限重为m
第i个物品重量为ai 输出n个数 求前i个物品 中 最少拿出多少个物品 使得能够装入背包(第i个答案一定包含第i个物品)
贪心即可:
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m) #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s); #define ll long long #define pb push_back #define inf 0x3f3f3f3f #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// const int N=2e5+5; int cnt[N],a[N]; int num; int main() { ll n,m,x; cin>>n>>m; rep(i,1,n) { RI(a[i]);int t=m-a[i],s=0; rep(j,1,100) { if(t>j*cnt[j])t-=j*cnt[j],s+=cnt[j]; else {s+=t/j;break;} } printf("%d ",i-1-s); ++cnt[a[i]]; } return 0; }
D. Extra Element
题意:给出n个数 要求能否去掉一个 使之成为一个等差数列
比赛的时候少考虑了一种方法wa到爆炸
首先将其排序 前三个数字分别为 abc
公差一共有三种可能 b-a c-b c-a 然后模拟即可求解 (比赛的时候少考虑了 c-a)
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m) #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s); #define ll long long #define pb push_back #define inf 0x3f3f3f3f #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// const int N=2e6+5; struct node { int pos; ll v; }a[N],b[N],c[N]; bool cmp(node a,node b) { return a.v<b.v; } int main() { int n;RI(n); if(n<=3){printf("1");return 0;} rep(i,1,n)scanf("%lld",&b[i].v),b[i].pos=i,a[i]=c[i]=b[i]; sort(a+1,a+1+n,cmp); sort(b+1,b+1+n,cmp); sort(c+1,c+1+n,cmp); ll d=a[2].v-a[1].v; int cnt=0; int ok=1; int flag=a[1].pos; rep(i,2,n) { if(a[i].v-a[i-1].v==d)continue; else { cnt++; a[i].v=a[i-1].v; flag=a[i].pos; if(cnt>1) { ok=0;break; } } } if(ok) { printf("%d",flag);return 0; } d=b[3].v-b[2].v; cnt=1; ok=1; flag=b[1].pos; rep(i,3,n) { if(b[i].v-b[i-1].v==d)continue; else { ok=0;break; } } if(ok) { printf("%d",flag);return 0; } d=c[3].v-c[1].v; ok=1; flag=c[2].pos; rep(i,4,n) { if(c[i].v-c[i-1].v==d)continue; else { ok=0;break; } } if(ok) { printf("%d",flag);return 0; } printf("-1"); return 0; }
超高效题解:
#include<bits/stdc++.h> using namespace std; #define F(i,a,b) for(int i=a;i<=(b);++i) #define F2(i,a,b) for(int i=a;i<(b);++i) #define dF(i,a,b) for(int i=a;i>=(b);--i) #define MN 200005 #define ll long long #define mod 998244353 int n; int a[MN],b[MN],c[MN]; map<int,int>mp; int cc; void ad(int x){if(mp[x]==0)++cc;++mp[x];} void su(int x){--mp[x];if(mp[x]==0)--cc;} void ans(int v){F(i,1,n)if(b[i]==v){printf("%d ",i);break;}} int main(){ scanf("%d",&n); if(n<=3)return puts("1"),0; F(i,1,n)scanf("%d",a+i),b[i]=a[i]; sort(a+1,a+n+1); F(i,1,n-1)c[i]=a[i+1]-a[i]; F(i,1,n-1)ad(c[i]); F(i,1,n){ if(i==1){ su(c[1]); if(cc==1)return ans(a[1]),0; ad(c[1]); } else if(i==n){ su(c[n-1]); if(cc==1)return ans(a[n]),0; ad(c[n-1]); } else{ su(c[i-1]),su(c[i]),ad(c[i-1]+c[i]); if(cc==1)return ans(a[i]),0; su(c[i-1]+c[i]),ad(c[i]),ad(c[i-1]); } } puts("-1"); return 0; }
E. Polycarp and Snakes
题意:给出一个n行m列的 . 阵表示什么都没有 上面可以加小写字母
判断是否是 输出所有字母条 要求满足条件:
小写字母可以被大写字母覆盖 (也就是说先画更小的)
同种字母只能是一条直线 且必须连续(除了被覆盖的情况)
字母必须升序(这点很好解决 直接完全覆盖即可 )
强行暴力即可 比较考验码力qaq
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m) #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s); #define ll long long #define pb push_back #define inf 0x3f3f3f3f #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// const int N=1e4; char mp[N][N]; int n,m,ans[N][4],cnt,vis[N]; map<int,pair<int,int> >pos; map<int,int>flag; int ok=1; void judge(int id,int x,int y,int flag) { int x1=x,x2=x,y1=y,y2=y; ++cnt; if(flag==0) { ans[cnt][0]=ans[cnt][2]=x; ans[cnt][1]=ans[cnt][3]=y; } else if(flag==1) { rep(i,y,m)if(mp[x][i]==id)x2=x,y2=i; repp(i,y,1)if(mp[x][i]==id)x1=x,y1=i; ans[cnt][0]=x1;ans[cnt][1]=y1,ans[cnt][2]=x2,ans[cnt][3]=y2; rep(i,y1,y2) if(mp[x][i]<id||mp[x][i]=='.')ok=0; } else if(flag==2) { rep(i,x,n)if(mp[i][y]==id) x2=i,y2=y; repp(i,x,1)if(mp[i][y]==id)x1=i,y1=y; ans[cnt][0]=x1;ans[cnt][1]=y1,ans[cnt][2]=x2,ans[cnt][3]=y2; rep(i,x1,x2) if(mp[i][y]<id||mp[i][y]=='.')ok=0; } vis[cnt]=id; } int main() { int cas;RI(cas); while(cas--) { cnt=0; vis[0]='a'-1; pos.clear();flag.clear(); RII(n,m); rep(i,1,n)RS(mp[i]+1); ok=1; rep(i,1,n)rep(j,1,m) { if(islower(mp[i][j])) { if(!pos.count(mp[i][j])) pos[mp[i][j]]=make_pair(i,j); else { if(pos[mp[i][j]].first!=i&&pos[mp[i][j]].second!=j)ok=0; if(pos[mp[i][j]].first==i) { if(flag[mp[i][j]]==2){ok=0;break;} else flag[mp[i][j]]=1; } else if(pos[mp[i][j]].second==j) { if(flag[mp[i][j]]==1){ok=0;break;} else flag[mp[i][j]]=2; } } } } if(!ok){puts("NO");continue;} rep(i,'a','z') if(pos.count(i)) { judge(i,pos[i].first,pos[i].second,flag[i]); if(!ok)break; } if(!ok){puts("NO");} else { puts("YES"); cout<<vis[cnt]-'a'+1<<endl; rep(i,1,cnt) { int temp=vis[i]-vis[i-1]; while(temp--) printf("%d %d %d %d ",ans[i][0],ans[i][1],ans[i][2],ans[i][3]); } } } return 0; }
F. Two Pizzas
题意:有n个人 每个人喜欢 某几种配料 有m个披萨 每个披萨 有一个价格 且 包含几种配料 (配料数小于9)
他们要订2个披萨 如果某个人的配料需求 全部被满足 说明这个人被满足
如何订披萨满足最多人的情况下 价格最小
一开始枚举披萨再枚举人 一共三重循环 直接超时了
考虑到 状态小 可以直接枚举状态
一开始维护每种相同披萨状态的最小价格
那么如果答案是买两个相同(配料披萨) 就wa了
所以要维护次小值
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m) #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s); #define ll long long #define see(x) (cerr<<(#x)<<'='<<(x)<<endl) #define pb push_back #define REP(i,N) for(int i=0;i<(N);i++) #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// #define inf 0x3f3f3f3f const int N=2e5+10; int n,m,x,a,ans1=1,ans2=2,maxx=0,temp,price,peo[N],minn1[N],minn2[N],id[N],id2[N]; ll money=1e14; int main() { RII(n,m); rep(i,1,n) { int s=0;RI(x); while(x--) { RI(a);s|=1<<(a-1); } peo[s]++; } rep(i,0,1<<9)minn1[i]=minn2[i]=inf; rep(i,1,m) { int s=0,c;RII(c,x); while(x--) { RI(a);s|=1<<(a-1); } if(c<minn1[s]){minn1[s]=c;id[s]=i;} else if(c<minn2[s]){minn2[s]=c;id2[s]=i;} } int tot=1<<9; rep(i,0,tot) rep(j,i+1,tot) if(minn1[i]<inf&&minn1[j]<inf) { int cnt=0; rep(k,0,tot)if( ((i|j)&k)==k )cnt+=peo[k]; if(cnt>maxx){maxx=cnt;ans1=id[i],ans2=id[j];money=minn1[i]+minn1[j]; } else if(cnt==maxx&&minn1[i]+minn1[j]<money){ans1=id[i],ans2=id[j];money=minn1[i]+minn1[j];} } rep(i,0,tot) if(minn1[i]<inf) { int cnt=0; rep(k,0,tot)if( ((i)&k)==k )cnt+=peo[k]; if(cnt==maxx&&minn1[i]+minn2[i]<money){ans1=id[i],ans2=id2[i];money=minn1[i]+minn2[i];} } cout<<ans1<<" "<<ans2; return 0; }
G1. Playlist for Polycarp (easy version)
题意:一个人有n首歌 时间为m
每首个有两个元素 时间和 种类 (一共三种)
要求求出 安排列表的数量 使得每个安排列表 总的时间恰好为m 且不会有两种相同种类的歌连续听
状压do[state][last] 表示 当前听的个的状态 和最后一首听的歌曲的种类
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m) #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s); #define ll long long #define pb push_back #define inf 0x3f3f3f3f #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// const int N=1e5; ll dp[1<<16][4]; const int mod=1e9+7; ll ans; int n,m; int t[N],v[N]; int main() { RII(n,m); rep(i,1,n)RII(t[i],v[i]),dp[1<<(i-1)][ v[i] ]=1 rep(state,0,(1<<n)-1 ) rep(last,1,3) rep(now,1,n) { if(state&1<<(now-1))continue; if(last==v[now])continue; int k=state|(1<<now-1); dp[k][ v[now] ]=(dp[k][v[now]]+dp[state][last])%mod; } rep(state,1,(1<<n)-1) { int sum=0; rep(j,1,n) { if(state&(1<<(j-1))) sum+=t[j]; } if(sum==m) { rep(k,1,3) ans=(ans+dp[state][k])%mod; } } cout<<ans; return 0; }