// 虽然是virtual participant但还是爽到、
A Vitaliy and Pie
题目链接:点击打开链接
思路:水题
AC代码:
#include <iostream> #include <iomanip> #include <algorithm> #include <cstring> #include <cstdio> #include <cstring> #include <string> #include <cmath> #include <string> #include <vector> #include <set> #include <map> #include <queue> using namespace std; #define FSIO ios::sync_with_stdio(0);cin.tie(0); #define DEBUG(a) cout<<"DEBUG: "<<(a)<<endl; const int MAXN = 100005; const int MOD = 1e9+7; const int INF = 1e9+7; int cnt[50]; int main() { FSIO; int N; string sst; while(cin>>N) { cin>>sst; memset(cnt,0,sizeof(cnt)); int ans = 0; for(int i=0;i<sst.length();++i) { if(sst[i]>='a'&&sst[i]<='z') cnt[sst[i]-'a']++; else { if(cnt[sst[i]-'A']==0) ans++; else cnt[sst[i]-'A']--; } } cout<<ans<<endl; } return 0; }
B Pasha and String
题目链接:点击打开链接
题意:给以串和n次反转操作,每次反转 a_i 到 len-a_i+1,(关于中心对称)
思路:从第一个字母到中间字母,用前缀和记录翻转操作次数,偶数不反转,奇数反转。
AC代码:
#include <iostream> #include <iomanip> #include <algorithm> #include <cstring> #include <cstdio> #include <cstring> #include <string> #include <cmath> #include <string> #include <vector> #include <set> #include <map> #include <queue> using namespace std; #define FSIO ios::sync_with_stdio(0);cin.tie(0); #define DEBUG(a) cout<<"DEBUG: "<<(a)<<endl; const int MAXN = 100005; const int MOD = 1e9+7; const int INF = 1e9+7; string nnn; int mk[MAXN]; int main() { FSIO; int M; while(cin>>nnn) { cin>>M; memset(mk,0,sizeof(mk)); int tmp; for(int i=1;i<=M;++i) { cin>>tmp; mk[tmp]++; } long long summ = 0; for(int i=0;i<nnn.length()/2;++i) { summ = summ + mk[i+1]; mk[i+1] = summ%2; if(mk[i+1]) swap(nnn[i],nnn[nnn.length()-i-1]); } cout<<nnn<<endl; } return 0; }
C Ilya and Cubes
题目链接:点击打开链接
题意:给你n根棍子,每根棍子长为a_i,每根棍子长度可以减1,使用四根如长为b, b, c, c的棍子可以拼成一个矩形。问这些棍子能拼成的最大举行面积之和。
思路:贪心。每根棍子只能和自己长度一样的或者少1长的棍子组合。故只需要排序,从大到小不断找这样组合累加就好了。
AC代码:
#include <iostream> #include <iomanip> #include <algorithm> #include <cstring> #include <cstdio> #include <cstring> #include <string> #include <cmath> #include <string> #include <vector> #include <set> #include <map> #include <queue> using namespace std; #define FSIO ios::sync_with_stdio(0);cin.tie(0); #define DEBUG(a) cout<<"DEBUG: "<<(a)<<endl; const int MAXN = 100005; const int MOD = 1e9+7; const int INF = 1e9+7; long long stick[MAXN]; long long curx, cury; int main() { FSIO; int N; while(cin>>N) { for(int i=1;i<=N;++i) cin>>stick[i]; long long ans = 0; curx = 0; sort(stick+1,stick+1+N); for(int i=N;i>=1;--i) { if(stick[i]==-1) continue; if(i>=2) { if(stick[i]-stick[i-1]>1) continue; if(curx!=0) { ans = ans + curx*min(stick[i],stick[i-1]); curx = 0; } else curx = min(stick[i],stick[i-1]); stick[i-1] = -1; } } cout<<ans<<endl; } return 0; }
D Arthur and Walls
题目链接:点击打开链接
题意:一个N x M的地方,*代表墙,相邻的 . 组合代表房间,现在要你敲掉最小的墙的数量将所有房间都变成矩形。问最后这块地方是怎样的。
思路:需要敲墙的时候,必然是对于四个邻接点有一个*,所以只需要不断地找这样的方格改变就好了。
AC代码:
#include <iostream> #include <iomanip> #include <algorithm> #include <cstring> #include <cstdio> #include <cstring> #include <string> #include <cmath> #include <string> #include <vector> #include <set> #include <map> #include <queue> using namespace std; #define FSIO ios::sync_with_stdio(0);cin.tie(0); #define DEBUG(a) cout<<"DEBUG: "<<(a)<<endl; const int MAXN = 2005; const int MOD = 1e9+7; const int INF = 1e9+7; char mapp[MAXN][MAXN]; int N, M; void dfs(int x, int y) { int cnt = 0; if(x+1>N||y+1>M||x<1||y<1) return; int ggx, ggy; ggx=ggy=-1; for(int i=x;i<=x+1;++i) for(int j=y;j<=y+1;++j) if(mapp[i][j]=='*') { ggx=i; ggy=j; cnt++; } if(cnt==1) { mapp[ggx][ggy] = '.'; dfs(x-1,y);dfs(x-1,y-1); dfs(x,y-1);dfs(x-1,y+1); dfs(x+1,y);dfs(x+1,y-1); dfs(x,y+1);dfs(x+1,y+1); } } int main() { FSIO; while(cin>>N>>M) { memset(mapp,0,sizeof(mapp)); for(int i=1;i<=N;++i) for(int j=1;j<=M;++j) cin>>mapp[i][j]; for(int i=1;i<N;++i) for(int j=1;j<M;++j) dfs(i,j); for(int i=1;i<=N;++i) { for(int j=1;j<=M;++j) cout<<mapp[i][j]; cout<<endl; } } return 0; }
E Anya and Cubes
题目链接:点击打开链接
题意:有n个立方体,上面标有数字num,你可以使用贴纸将其变为num!。现在给你n个立方体,k个贴纸,和一个数字S,要你求经过一系列操作之后选则一定数量的立方体求其上数字之和为S的方案数。
思路:首先,S范围不超过1e16,故只有原标数字小于19的立方体贴纸才有意义。而一个立方体只有三种可能,即不取,取原数字,取原数字的阶乘。
考虑到暴力枚举所有方案,很难存储下这么多数据。
故不妨将原盒子分为两部分来凑成S。这样复杂度变为O(12^3 * 13^3 * 25),而考虑到每次枚举完后,k不可能每次都那么大,故复杂度近似为O(1e9)。
AC代码如下:
#include <iostream> #include <iomanip> #include <algorithm> #include <cstring> #include <cstdio> #include <cstring> #include <string> #include <cmath> #include <string> #include <vector> #include <set> #include <map> #include <queue> using namespace std; #define FSIO ios::sync_with_stdio(0);cin.tie(0); #define DEBUG(a) cout<<"DEBUG: "<<(a)<<endl; const int MAXN = 100005; const int MOD = 1e9+7; const int INF = 1e9+7; long long fac[25]; map<long long, int> res[30]; long long num[30]; long long S; int n, k, mid; long long ans; void init() { fac[0] = 1; for(int i=1;i<19;++i) fac[i] = (long long)i*fac[i-1]; } void foredfs(int index, int kki, long long summ) { if(kki>k||summ>S) return ; if(index>n) { res[kki][summ]++; return; } if(num[index]<19) foredfs(index+1,kki+1,summ+fac[num[index]]); foredfs(index+1,kki,summ+num[index]); foredfs(index+1,kki,summ); } void aftdfs(int index, int kki, long long summ) { if(kki>k||summ>S) return ; if(index>mid) { for(int i=0;i<=k-kki;++i) ans = ans + res[i][S-summ]; return; } if(num[index]<19) aftdfs(index+1,kki+1,summ+fac[num[index]]); aftdfs(index+1,kki,summ+num[index]); aftdfs(index+1,kki,summ); } int main() { init(); while(scanf("%d%d%I64d",&n,&k,&S)!=EOF) { for(int i=1;i<=n;++i) scanf("%I64d",num+i); ans = 0; for(int i=0;i<=k;++i) res[i].clear(); mid = n/2; foredfs(mid+1,0,0); aftdfs(1,0,0); printf("%I64d\n",ans); } return 0; }