The 10th Shandong Provincial Collegiate Programming Contest
The 10th Shandong Provincial Collegiate Programming Contest
思路:将日期转换为天数,求出差值对5取模
#include<bits/stdc++.h> using namespace std; #define int long long //#define int __int128 typedef pair<int,int>PII; typedef pair<string,int>PSI; typedef pair<string,string>PSS; const int N=2e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353; const double eps=1e-6; map<string,int>si; string is[5]; void init(){ si["Monday"]=0; si["Tuesday"]=1; si["Wednesday"]=2; si["Thursday"]=3; si["Friday"]=4; is[0]="Monday"; is[1]="Tuesday"; is[2]="Wednesday"; is[3]="Thursday"; is[4]="Friday"; } void solve(){ int y1,m1,d1,y2,m2,d2; string s1,s2; cin>>y1>>m1>>d1>>s1>>y2>>m2>>d2; int x1=y1*12*30+m1*30+d1; int x2=y2*12*30+m2*30+d2; x2-=x1; int p=si[s1]; p+=x2; p=(p%5+5)%5; cout<<is[p]<<'\n'; } signed main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int t=1; init(); cin>>t; while(t--){ solve(); } return 0; }
思路:将001→100,看作101→000,实际是一样的,变为最终状态只需要对第一和第三个操作一次即可,过程中的其他次数实际一样;所以初始串可转变为两串异或后的状态;
考虑dp来写,f[i][j]表示前i轮,且第i轮有j盏灯亮的方案数;
x表示上一轮1的数目,l表示这一轮对0操作的数目,则这一轮对1操作的数目为m-l;
对上一轮操作后,j=x+l-(m-l),即x=m+j-2l
从上一轮的n-x中选l个0,有C(n-x,l)种可能;从上一轮的x中选m-l个1,有C(x,m-l)种可能;
且保证l<=n-x和m-l<=x,则l<=j
则有f[i][j]+=f[i-1][x]*C(n-x,l)*C(x,m-l)
#include<bits/stdc++.h> using namespace std; #define int long long //#define int __int128 typedef pair<int,int>PII; typedef pair<string,int>PSI; typedef pair<string,string>PSS; const int N=2e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353; const double eps=1e-6; int c[105][105]; void init(){ for(int i=0;i<=100;++i){ for(int j=0;j<=i;++j){ if(!j)c[i][j]=1; else c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod; } } } void solve(){ int n,k,m;cin>>n>>k>>m; string s1,s2;cin>>s1>>s2; int cnt1=0; for(int i=0;i<n;++i) cnt1+=s1[i]!=s2[i]; vector<vector<int>>f(k+1,vector<int>(n+1,0)); f[0][cnt1]=1; for(int i=1;i<=k;++i) for(int j=0;j<=n;++j) for(int l=0;l<=j&&l<=m;++l){ int x=m+j-2*l; if(x<0||x>n||l>n-x)continue; f[i][j]=(f[i][j]+f[i-1][x]*c[n-x][l]%mod*c[x][m-l]%mod)%mod; } cout<<f[k][0]<<'\n'; } signed main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int t=1; init(); cin>>t; while(t--){ solve(); } return 0; }
思路:每操作n次,发现增量都是相同的,增量为第一轮操作第n次的下标(a,b);对于同一个操作,每次的距离一定大于上一次,那么只需要找到第1轮和第k轮操作后的距离的最大值
#include<bits/stdc++.h> using namespace std; #define int long long //#define int __int128 typedef pair<int,int>PII; typedef pair<string,int>PSI; typedef pair<string,string>PSS; const int N=2e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353; const double eps=1e-6; void init(){ } void solve(){ int n,k;cin>>n>>k; string s;cin>>s; int ans=0; vector<int>x(n+1),y(n+1); for(int i=1;i<=n;++i){ x[i]=x[i-1],y[i]=y[i-1]; if(s[i-1]=='U')y[i]++; else if(s[i-1]=='D')y[i]--; else if(s[i-1]=='L')x[i]--; else x[i]++; ans=max(ans,abs(x[i])+abs(y[i])); } for(int i=1;i<=n;++i){ ans=max(ans,abs(x[i]+x[n]*(k-1))+abs(y[i]+y[n]*(k-1))); } cout<<ans<<'\n'; } signed main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int t=1; init(); cin>>t; while(t--){ solve(); } return 0; }
思路:一个连通图最少要n-1条边,所以最大的操作次数为x=m-(n-1),即输的人为x%k
#include<bits/stdc++.h> using namespace std; #define int long long //#define int __int128 typedef pair<int,int>PII; typedef pair<string,int>PSI; typedef pair<string,string>PSS; const int N=2e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353; const double eps=1e-6; void init(){ } void solve(){ int k;cin>>k; string s;cin>>s; int n,m;cin>>n>>m; for(int i=0,u,v;i<m;++i)cin>>u>>v; int p=m-(n-1); if(s[p%k]=='1')cout<<2<<'\n'; else cout<<1<<'\n'; } signed main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int t=1; init(); cin>>t; while(t--){ solve(); } return 0; }
思路:总数为all时,每个人为all/n是最优情况,则取最近的n的倍数(倍数越小说明第一次操作会多n,且小于平均值的数最多会少n次操作,并不会减少操作,可能会增加);第一种操作次数即为多出n的倍数的石头,第二种由于多出和少出平均值的数量是相等的,算少的即可
#include<bits/stdc++.h> using namespace std; #define int long long //#define int __int128 typedef pair<int,int>PII; typedef pair<string,int>PSI; typedef pair<string,string>PSS; const int N=2e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353; const double eps=1e-6; void init(){ } void solve(){ int n,all=0;cin>>n; vector<int>ve(n); for(int i=0;i<n;++i)cin>>ve[i],all+=ve[i]; int k=all/n; int ans=all%n;//第一种 for(int i=0;i<n;++i)//第二种 if(ve[i]<k)ans+=k-ve[i]; cout<<ans<<'\n'; } signed main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int t=1; init(); cin>>t; while(t--){ solve(); } return 0; }
思路:按左右端点排序,优先选择右端点小的,用堆维护
#include<bits/stdc++.h> using namespace std; #define int long long //#define int __int128 typedef pair<int,int>PII; typedef pair<string,int>PSI; typedef pair<string,string>PSS; const int N=2e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353; const double eps=1e-6; void init(){ } void solve(){ int n;cin>>n; vector<PII>ve(n); for(int i=0;i<n;++i)cin>>ve[i].first>>ve[i].second; sort(ve.begin(),ve.end()); priority_queue<int,vector<int>,greater<int>>q; int idx=0,l,ans=0; while(1){ while(q.size()&&q.top()<l)q.pop(); if(q.empty()){ if(idx>=n)break; l=ve[idx].first; }else{ ans++;q.pop(); l++; } while(idx<n&&ve[idx].first<=l){ q.push(ve[idx].second);idx++; } } cout<<ans<<'\n'; } signed main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int t=1; init(); cin>>t; while(t--){ solve(); } return 0; }
思路:a,x的奇偶性相同(因为都对偶数取模),且打表得出a为奇数时,答案为1。(¿)
a为偶数时,令 a=t1*2q → ax=t1x*2qx
若axmod2p为0,则qx>=p,x>=p/q;由于q>=1(a为偶数),则x>=p;
x与a同为偶数,令x'=t2*2k → x'a=t2a*2ka
若x'amod2p为0,则ka>=p,k>=p/a(上取)=k';
在[p,2p]中,x取2k'的倍数即可满足xamod2p为0,个数有2p-k'-(p-1)/2k'
在[1,p)中,枚举x即可;(p<=30)
#include<bits/stdc++.h> using namespace std; #define int long long //#define int __int128 typedef pair<int,int>PII; typedef pair<string,int>PSI; typedef pair<string,string>PSS; const int N=2e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353; const double eps=1e-6; int mmod; int ksm(int x,int y){ int res=1; while(y){ if(y&1)res=res*x%mmod; x=x*x%mmod; y>>=1; } return res; } void solve(){ int a,p;cin>>a>>p; mmod=1<<p; if(a&1){ cout<<"1\n";return ; } int ans=0; for(int i=1;i<p;++i) ans+=ksm(a,i)==ksm(i,a); int y=(p+a-1)/a; ans+=(1<<(p-y))-(p-1)/(1<<y); cout<<ans<<'\n'; } signed main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int t=1; //init(); cin>>t; while(t--){ solve(); } return 0; }
思路:一条关系可以看作一条有向边,由大的指向小的,得到一张有向图,先判断有无环,有环说明情况不存在全为0;可用bfs或dfs判断,同时记录该点的前继和后继;若该点为中位点,说明该点的前继和后继都不超过n/2
#include<bits/stdc++.h> using namespace std; #define int long long //#define int __int128 typedef pair<int,int>PII; typedef pair<string,int>PSI; typedef pair<string,string>PSS; const int N=2e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353; const double eps=1e-6; void init(){ } void solve(){ int n,m;cin>>n>>m; vector<int>g[n+1],vis(n+1,0),up(n+1),low(n+1); for(int i=0,u,v;i<m;++i){ cin>>u>>v; g[u].push_back(v); } auto bfs=[&](int u){ queue<int>q; q.push(u);vis[u]=u; while(q.size()){ int t=q.front();q.pop(); for(auto v:g[t]){ if(v==u)return false; if(vis[v]==u)continue; vis[v]=u;q.push(v); low[u]++,up[v]++; } } return true; }; for(int i=1;i<=n;++i){ if(!bfs(i)){ for(int j=1;j<=n;++j)cout<<"0";cout<<'\n'; return ; } } for(int i=1;i<=n;++i) if(low[i]<=n/2&&up[i]<=n/2)cout<<"1"; else cout<<"0";cout<<'\n'; } signed main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int t=1; init(); cin>>t; while(t--){ solve(); } return 0; }
思路:当n<=1时,答案就为n
#include<bits/stdc++.h> using namespace std; #define int long long //#define int __int128 typedef pair<int,int>PII; typedef pair<string,int>PSI; typedef pair<string,string>PSS; const int N=2e5+5,INF=0x3f3f3f3f,Mod=1e9+7,mod=998244353; const double eps=1e-6; void init(){ } void solve(){ int n,k;cin>>n>>k; while(k&&n>1){ n=(n+1)/2;k--; } cout<<n<<'\n'; } signed main(){ ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int t=1; init(); cin>>t; while(t--){ solve(); } return 0; }