2019年湘潭大学程序设计竞赛
Problem A?Who's better?
https://ac.nowcoder.com/acm/contest/893/A
題意:模擬ACM比賽計分規則
題解:模擬
C++版本一
/* *@Author: STZG *@Language: C++ */ #include <bits/stdc++.h> #include<iostream> #include<algorithm> #include<cstdlib> #include<cstring> #include<cstdio> #include<string> #include<vector> #include<bitset> #include<queue> #include<deque> #include<stack> #include<cmath> #include<list> #include<map> #include<set> //#define DEBUG #define RI register int #define endl "\n" using namespace std; typedef long long ll; //typedef __int128 lll; const int N=100000+10; const int M=100000+10; const int MOD=1e9+7; const double PI = acos(-1.0); const double EXP = 1E-8; const int INF = 0x3f3f3f3f; int t,n,m,k,p,l,r,u,v; int ans,cnt,flag,temp,sum; int a[2][3]; char str; struct node{}; int main() { #ifdef DEBUGfreopen("input.in", "r", stdin);//freopen("output.out", "w", stdout); #endif//ios::sync_with_stdio(false);//cin.tie(0);//cout.tie(0);//scanf("%d",&t);//while(t--){for(int i=0;i<2;i++){for(int j=0;j<3;j++){scanf("%d",&a[i][j]);}}if(a[0][0]>a[1][0]){cout<<1<<endl;}else if(a[0][0]<a[1][0]){cout<<2<<endl;}else{if(a[0][1]<a[1][1]){cout<<1<<endl;}else if(a[0][1]>a[1][1]){cout<<2<<endl;}else{if(a[0][2]<a[1][2]){cout<<1<<endl;}else if(a[0][2]>a[1][2]){cout<<2<<endl;}else{cout<<"God"<<endl;}}}//}#ifdef DEBUGprintf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC); #endif//cout << "Hello world!" << endl;return 0; }Problem B?Number
https://ac.nowcoder.com/acm/contest/893/B
題意:
- 如果n的最后一位數碼是0,那么她就把n除以10;
- 否則她把這個數加上1;
- 直到n變為一個不大于1的數。
給定n,請問需要做多少次操作?
題解:模擬
C++版本一
/* *@Author: STZG *@Language: C++ */ #include <bits/stdc++.h> #include<iostream> #include<algorithm> #include<cstdlib> #include<cstring> #include<cstdio> #include<string> #include<vector> #include<bitset> #include<queue> #include<deque> #include<stack> #include<cmath> #include<list> #include<map> #include<set> //#define DEBUG #define RI register int #define endl "\n" using namespace std; typedef long long ll; //typedef __int128 lll; const int N=100000+10; const int M=100000+10; const int MOD=1e9+7; const double PI = acos(-1.0); const double EXP = 1E-8; const int INF = 0x3f3f3f3f; int t,n,m,k,p,l,r,u,v; int ans,cnt,flag,temp,sum; int a[N]; char str; struct node{}; int main() { #ifdef DEBUGfreopen("input.in", "r", stdin);//freopen("output.out", "w", stdout); #endif//ios::sync_with_stdio(false);//cin.tie(0);//cout.tie(0);scanf("%d",&t);while(t--){scanf("%d",&n);ans=0;while(n>1){while(n%10==0)ans++,n/=10;if(n<=1)break;n++;ans++;}cout<<ans<<endl;}#ifdef DEBUGprintf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC); #endif//cout << "Hello world!" << endl;return 0; }Problem C?Math Problem
https://ac.nowcoder.com/acm/contest/893/C
題意:已知整數a,除192的余數是1。求區間[L,R]之間滿足條件的a的累加和是多少?
題解:規律
樸素打表(見代碼注釋)
證明:
C++版本一
/* *@Author: STZG *@Language: C++ */ #include <bits/stdc++.h> #include<iostream> #include<algorithm> #include<cstdlib> #include<cstring> #include<cstdio> #include<string> #include<vector> #include<bitset> #include<queue> #include<deque> #include<stack> #include<cmath> #include<list> #include<map> #include<set> //#define DEBUG #define RI register int #define endl "\n" using namespace std; typedef long long ll; //typedef __int128 lll; const int N=100000+10; const int M=100000+10; const int MOD=1e9+7; const double PI = acos(-1.0); const double EXP = 1E-8; const int INF = 0x3f3f3f3f; ll t,n,m,k,p,l,r,u,v; ll ans,cnt,flag,temp,sum; int a[N]; char str; struct node{}; int main() { #ifdef DEBUGfreopen("input.in", "r", stdin);//freopen("output.out", "w", stdout); #endif//ios::sync_with_stdio(false);//cin.tie(0);//cout.tie(0);scanf("%lld",&t);while(t--){scanf("%lld%lld",&l,&r); // ans=0; // ans=r/192-(l-1)/192; // if(r%192) // ans++; // if((l-1)%192) // ans--;//cnt=0; // sum=0; // for(ll i=l;i<=r;i++){ // if((i*i*i)%192==1){ // cnt++;sum+=i; // cout<<i<<endl; // } // }//cout<<sum<<endl;r=(r%192==0)?r/192:r/192+1;//r=r*192+1;l--;l=(l%192==0)?l/192:l/192+1;//l=l*192+1;//cout<<l<<" "<<r<<endl;cout<<r+r*(r-1)*96-l-l*(l-1)*96<<endl;}#ifdef DEBUGprintf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC); #endif//cout << "Hello world!" << endl;return 0; }Problem D?Stone
https://ac.nowcoder.com/acm/contest/893/D
題意:將所有的石子合并成一堆,你所消耗的體力最小是多少?
題解:貪心
石子數累加和 -最大一堆的石子數量
C++版本一
/* *@Author: STZG *@Language: C++ */ #include <bits/stdc++.h> #include<iostream> #include<algorithm> #include<cstdlib> #include<cstring> #include<cstdio> #include<string> #include<vector> #include<bitset> #include<queue> #include<deque> #include<stack> #include<cmath> #include<list> #include<map> #include<set> //#define DEBUG #define RI register int #define endl "\n" using namespace std; typedef long long ll; //typedef __int128 lll; const int N=100000+10; const int M=100000+10; const int MOD=1e9+7; const double PI = acos(-1.0); const double EXP = 1E-8; const int INF = 0x3f3f3f3f; int t,n,m,k,p,l,r,u,v; ll ans,cnt,flag,temp,sum; ll a[N]; char str; struct node{}; int main() { #ifdef DEBUGfreopen("input.in", "r", stdin);//freopen("output.out", "w", stdout); #endif//ios::sync_with_stdio(false);//cin.tie(0);//cout.tie(0);scanf("%d",&t);while(t--){scanf("%d",&n);ans=0;sum=0;for(int i=1;i<=n;i++)scanf("%lld",&a[i]),ans=max(ans,a[i]),sum+=a[i];cout<<sum-ans<<endl;}#ifdef DEBUGprintf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC); #endif//cout << "Hello world!" << endl;return 0; }Problem E?Watermelon
https://ac.nowcoder.com/acm/contest/893/E
題意:
題解:
C++版本一
題解:原博客
先對于問題進行分析,我們假設,如果lililalala(以下簡稱拉拉)一定是第一個人的話,那問題就會變得很明確:拉拉后面的人要做到在經過x輪之后使得剛好把西瓜吃完。
所以,我們可以對給出的數據進行改造,使得拉拉變成我們想要的第一個人。
怎么改造呢?其實枚舉就可以,從每個人吃一個到每個人吃自己的肚量逐一枚舉。但由于a[i]的數據范圍過大,需要進行一些特判:
經過上面的特判,其實我們已經把枚舉范圍壓縮到了小于m(1e6),在時間復雜度上是允許的。
然后我們就可以開始枚舉:
函數中也加了特判:
1.如果x為0,那就是剛好輪到拉拉時沒得吃.
2.如果拉拉吃掉西瓜之后,接下來每個人就算一人只吃一個也無法結束這輪,那就無解.
然后我們求出游戲進行的最大輪數r和最小輪數l,也就是除了拉拉外所有人一次只吃一個和除了拉拉外所有人每次都吃最多的輪數。
顯然可得,當這兩個輪數不同時必然有解,證明如下:
如果l!=r,那我們肯定有辦法控制在任意(l+1,r)輪之間剛好結束,這樣就能使得拉拉在下一輪開始無法吃到西瓜,從而勝利。
如果l=r呢?首先我們要考慮到如果 l 或 r 為剛好結束一輪,那樣也是直接勝利。否則得話,我們吃再多或者再少也無法在其他輪次結束游戲,也就是說,我們無法使得輪到拉拉時西瓜,所以無解。
int f(LL x){if(x==0){return 1;}if(x<n-1+a[mx]){return 0;}if(x<=s[n])return 1;if(x%(n-1+a[mx])==0)return 1;LL l=x/s[n],r=x/(n-1+a[mx]);if(l!=r){return 1;}else{return 0;}?
最后,最最重要的一個特判(因為少了這個特判我wa了22發并且沒過!!),那就是:如果只有一個人,也就是只有拉拉自己時,必定是他打掃衛生(我恨啊!)。
?
C++版本二
/* *@Author: STZG *@Language: C++ */ #include <bits/stdc++.h> #include<iostream> #include<algorithm> #include<cstdlib> #include<cstring> #include<cstdio> #include<string> #include<vector> #include<bitset> #include<queue> #include<deque> #include<stack> #include<cmath> #include<list> #include<map> #include<set> //#define DEBUG #define RI register int #define endl "\n" using namespace std; typedef long long ll; //typedef __int128 lll; const int N=100000+10; const int M=100000+10; const int MOD=1e9+7; const double PI = acos(-1.0); const double EXP = 1E-8; const int INF = 0x3f3f3f3f; int t,n,m,k,p; ll l,r,u,v; ll ans,cnt,flag,temp,sum; int a[N]; char str; struct node{}; int main() { #ifdef DEBUGfreopen("input.in", "r", stdin);//freopen("output.out", "w", stdout); #endif//ios::sync_with_stdio(false);//cin.tie(0);//cout.tie(0);scanf("%d",&t);while(t--){scanf("%d%d",&n,&m);int pos=0;int maxl=0;sum=0;for(int i=1;i<=n;i++){scanf("%d",&a[i]);sum+=a[i];if(maxl<a[i]){maxl=a[i];pos=i;}}l=0;r=0;for(int i=1;i<pos;i++){l+=1;r+=a[i];}//l+=a[pos];//r+=a[pos];flag=0;while(l<=m){//cout<<pos<<" "<<l<<" "<<r<<endl;if(m<=r){flag=1;break;}l+=n-1+a[pos];r+=sum;}cout<<(flag||n==1?"YES":"NO")<<endl;}#ifdef DEBUGprintf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC); #endif//cout << "Hello world!" << endl;return 0; }Problem F?Black & White
https://ac.nowcoder.com/acm/contest/893/F
題意:對S字符串中,兩個操作:0變成1,1變成0,求S在經過最多m次操作后的最大價值
題解:
C++版本一
題解:DP
/* *@Author: STZG *@Language: C++ */ #include <bits/stdc++.h> #include<iostream> #include<algorithm> #include<cstdlib> #include<cstring> #include<cstdio> #include<string> #include<vector> #include<bitset> #include<queue> #include<deque> #include<stack> #include<cmath> #include<list> #include<map> #include<set> //#define DEBUG #define RI register int #define endl "\n" using namespace std; typedef long long ll; //typedef __int128 lll; const int N=100000+10; const int M=100000+10; const int MOD=1e9+7; const double PI = acos(-1.0); const double EXP = 1E-8; const int INF = 0x3f3f3f3f; int t,n,m,k,p,l,r,u,v; int ans,cnt,flag,temp; int a[N]; char str[N]; int pos[2][N],num[2]; struct node{}; int main() { #ifdef DEBUGfreopen("input.in", "r", stdin);//freopen("output.out", "w", stdout); #endif//ios::sync_with_stdio(false);//cin.tie(0);//cout.tie(0);scanf("%d",&t);while(t--){scanf("%d%d",&n,&m);scanf("%s",str+1);ans=0;memset(pos,0,sizeof(pos));num[0]=num[1]=0;for(int i=1;i<=n;i++){if(str[i]=='0'){num[0]++;pos[0][num[0]]=i;}else{num[1]++;pos[1][num[1]]=i;}ans=max(ans,i-pos[1][max(0,num[1]-m)]);ans=max(ans,i-pos[0][max(0,num[0]-m)]);}cout<<ans<<endl;}#ifdef DEBUGprintf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC); #endif//cout << "Hello world!" << endl;return 0; }C++版本二
題解:二分 + 前綴和
Problem G?Truthman or Fakeman
https://ac.nowcoder.com/acm/contest/893/G
題意:
題解:二分圖+建模
C++版本一
/* *@Author: STZG *@Language: C++ */ #include <bits/stdc++.h> #include<iostream> #include<algorithm> #include<cstdlib> #include<cstring> #include<cstdio> #include<string> #include<vector> #include<bitset> #include<queue> #include<deque> #include<stack> #include<cmath> #include<list> #include<map> #include<set> //#define DEBUG #define RI register int #define endl "\n" using namespace std; typedef long long ll; //typedef __int128 lll; const int N=100000+10; const int M=100000+10; const int MOD=1e9+7; const double PI = acos(-1.0); const double EXP = 1E-8; const int INF = 0x3f3f3f3f; int t,n,m,k,p,l,r,u,v,w; int ans,cnt,flag,temp,sum; int vis[N],VIS[N]; char str; struct node{int v,w;node(){};node(int _v,int _w):v(_v),w(_w){} }; vector<node>G[N]; bool dfs(int u,int col){++sum;cnt+=col;vis[u]=col;bool res=1;for(int i=0,j=G[u].size();i<j;i++){int v=G[u][i].v;int val=G[u][i].w?col:!col;if(vis[v]==-1){res&=dfs(v,val);}else{res&=val==vis[v];}}return res; } void DFS(int u){vis[u]=!vis[u];VIS[u]=1;for(int i=0,j=G[u].size();i<j;i++){int v=G[u][i].v;if(!VIS[v])DFS(v);} }int main() { #ifdef DEBUGfreopen("input.in", "r", stdin);//freopen("output.out", "w", stdout); #endif//ios::sync_with_stdio(false);//cin.tie(0);//cout.tie(0);scanf("%d",&t);while(t--){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){G[i].clear();vis[i]=-1;VIS[i]=0;}for(int i=1;i<=m;i++){scanf("%d%d%d",&u,&v,&w);G[u].push_back({v,w});G[v].push_back({u,w});}ans=1;for(int i=1;i<=n;i++){if(vis[i]==-1){sum=cnt=0;ans&=dfs(i,1);if(cnt+cnt<sum){DFS(i);}}}if(ans){for(int i=1;i<=n;i++){cout<<vis[i];}cout<<endl;}else{cout<<-1<<endl;}}#ifdef DEBUGprintf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC); #endif//cout << "Hello world!" << endl;return 0; }C++版本二
/* *@Author: STZG *@Language: C++ */ #include <bits/stdc++.h> #include<iostream> #include<algorithm> #include<cstdlib> #include<cstring> #include<cstdio> #include<string> #include<vector> #include<bitset> #include<queue> #include<deque> #include<stack> #include<cmath> #include<list> #include<map> #include<set> //#define DEBUG #define RI register int #define endl "\n" using namespace std; typedef long long ll; //typedef __int128 lll; const int N=100000+10; const int M=100000+10; const int MOD=1e9+7; const double PI = acos(-1.0); const double EXP = 1E-8; const int INF = 0x3f3f3f3f; int t,n,m,k,p,l,r,u,v,w; int ans,cnt,flag,temp,sum,tot; int vis[N],VIS[N],TF[N]; char str; struct node{int v,w;node(){};node(int _v,int _w):v(_v),w(_w){} }; vector<node>G[N]; bool dfs(int u,int col){++sum;cnt+=col;vis[u]=col;VIS[u]=tot;bool res=1;for(int i=0,j=G[u].size();i<j;i++){int v=G[u][i].v;int val=G[u][i].w?col:!col;if(vis[v]==-1){res&=dfs(v,val);}else{res&=val==vis[v];}}return res; } int main() { #ifdef DEBUGfreopen("input.in", "r", stdin);//freopen("output.out", "w", stdout); #endif//ios::sync_with_stdio(false);//cin.tie(0);//cout.tie(0);scanf("%d",&t);while(t--){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){G[i].clear();vis[i]=-1;VIS[i]=0;}for(int i=1;i<=m;i++){scanf("%d%d%d",&u,&v,&w);G[u].push_back({v,w});G[v].push_back({u,w});}ans=1;tot=0;for(int i=1;i<=n;i++){if(vis[i]==-1){sum=cnt=0;tot++;ans&=dfs(i,1);TF[tot]=cnt+cnt<sum;}}if(ans){for(int i=1;i<=n;i++){cout<<(TF[VIS[i]]^vis[i]);}cout<<endl;}else{cout<<-1<<endl;}}#ifdef DEBUGprintf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC); #endif//cout << "Hello world!" << endl;return 0; }?
Problem H?Chat
https://ac.nowcoder.com/acm/contest/893/H
題意:
題解:
C++版本一?
題解:原博客
對題目進行分析,要求的是使女神總生氣度不超過k的最小總上線時間,換句話說那就是(咕了女神k小時使得我們獲得的最大不在線時間)。想到這點接下來就可以寫了。
首先我們對每天女神在線時間的做個預處理,統計下前綴和和個數。
? scanf("%s",a+1);for(int j=1;j<=m;j++){if(a[j]=='0')f[j]=f[j-1];else f[j]=f[j-1]+1,cnt[i]++;}然后假使咕了女神所有的在線時間,那我們得到的價值當然就是一整天了,也就是
? ? s[i][cnt[i]]=m;然后,因為數據比較小,我們再直接跑個m方的暴力就可以求出在第i天咕女神x(x<cnt[i])次所帶來的最大休息時間。
for(int p=1;p<=m;p++){for(int q=p;q<=m;q++){s[i][cnt[i]-f[q]+f[p-1]]=max(s[i][cnt[i]-f[q]+f[p-1]],m-(q-p+1));/*(p,q)為我假設的在線時間,通過前綴和計算得出(p,q)之間的女神在線時長:f[q]-f[p-1].所以咕了女神的時間x即是 cnt[i]-(f[q]-f[p-1])然后我們因此獲得的休息時間t是 m-(p-q+1)所以在這一天咕女神x小時獲得的休息時間可以更新為 min(s[i][x],t)也就是 s[i][x]=min(s[i][x],t)*/}}算完所有天的情況后,就是一個背包了:已知每天咕女神 0到cnt[i] 小時所帶來的價值,最多可以咕k個小時,請問我怎么取能使得到的價值最大?
因為每天只能選擇一種情況,所以是分組背包,開個二維數組記錄一下
顯然可得我們取k個小時肯定是最優的,因為對于任意k-1的情況,我們可以在他的基礎上再咕掉任意一個還沒咕的小時,再向前推也是同理。
for(int i=1;i<=n;i++){//第i天for(int j=0;j<=cnt[i];j++){//咕女神j個小時for(int l=k;l>=j;l--){//從后往前更新ans[i][l]=max(ans[i][l],ans[i-1][l-j]+s[i][j]);}} }所以我們就求得了答案ans[n][k]
然后我們要求的是花的最小時間,也就是總時間減去最大休息時間,輸出即可。
#include <bits/stdc++.h> using namespace std; #define LL long long #define FI first #define SE second #define PB push_back #define POP pop_back #define D double #define endl '\n' typedef pair<int,int> PII; const LL INF=1e18,mod=100000000; const int N=2e5+7; int n,m,k; char a[222]; int s[222][222];//第一維表示天數,第二維表示改天咕女神的小時數,也就是在第i天咕女神j小時獲得的最大不在線時間 int f[222];//統計每天女神在線時長的前綴和用的滾動數組 int cnt[222];//女神每天的在線時長 int ans[222][222];//二維背包容器 int main() {int t;cin>>t;while(t--){memset(s,0,sizeof(s));memset(cnt,0,sizeof(cnt));scanf("%d%d%d",&n,&m,&k);for(int i=1;i<=n;i++){scanf("%s",a+1);for(int j=1;j<=m;j++){if(a[j]=='0')f[j]=f[j-1];else f[j]=f[j-1]+1,cnt[i]++;}s[i][cnt[i]]=m;for(int p=1;p<=m;p++){for(int q=p;q<=m;q++){s[i][cnt[i]-f[q]+f[p-1]]=max(s[i][cnt[i]-f[q]+f[p-1]],m-(q-p+1));}}}int num=m*n;memset(ans,0,sizeof(ans));for(int i=1;i<=n;i++){for(int j=0;j<=cnt[i];j++){for(int l=k;l>=j;l--){ans[i][l]=max(ans[i][l],ans[i-1][l-j]+s[i][j]);}}}printf("%d\n",num-ans[n][k]);}return 0; }C++版本二
/* *@Author: STZG *@Language: C++ */ #include <bits/stdc++.h> #include<iostream> #include<algorithm> #include<cstdlib> #include<cstring> #include<cstdio> #include<string> #include<vector> #include<bitset> #include<queue> #include<deque> #include<stack> #include<cmath> #include<list> #include<map> #include<set> //#define DEBUG #define RI register int #define endl "\n" using namespace std; typedef long long ll; //typedef __int128 lll; const int N=200+10; const int M=100000+10; const int MOD=1e9+7; const double PI = acos(-1.0); const double EXP = 1E-8; const int INF = 0x3f3f3f3f; int t,n,m,k,p,l,r; int ans,cnt[N],flag,temp,sum; int v[N][N],dp[N][N],a[N]; char str[N][N]; struct node{}; int main() { #ifdef DEBUGfreopen("input.in", "r", stdin);//freopen("output.out", "w", stdout); #endif//ios::sync_with_stdio(false);//cin.tie(0);//cout.tie(0);scanf("%d",&t);while(t--){scanf("%d%d%d",&n,&m,&p);memset(a,0,sizeof(a));memset(cnt,0,sizeof(cnt));memset(v,0,sizeof(v));for(int i=1;i<=n;i++){scanf("%s",str[i]+1);for(int j=1;j<=m;j++){if(str[i][j]=='1'){a[++cnt[i]]=j;}}v[i][cnt[i]]=m;for(int j=0;j<cnt[i];j++){for(int k=1;k+j<=cnt[i];k++){v[i][cnt[i]-j-1]=max(v[i][cnt[i]-j-1],m-a[k+j]+a[k]-1);}}}memset(dp,0,sizeof(dp));for(int i=1;i<=n;i++){for(int j=0;j<=cnt[i];j++){for(int k=p;k>=j;k--){dp[i][k]=max(dp[i][k],dp[i-1][k-j]+v[i][j]);}}}ans=n*m-dp[n][p];cout<<ans<<endl;}#ifdef DEBUGprintf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC); #endif//cout << "Hello world!" << endl;return 0; }?
總結
以上是生活随笔為你收集整理的2019年湘潭大学程序设计竞赛的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 上白泽慧音
- 下一篇: [ZJOI2009]假期的宿舍