AB
签到(A过水已隐藏)
#include<bits/stdc++.h> using namespace std; const int N=505; int n,m,vis[N][N]; char mp[N][N]; int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%s",mp[i]+1); if(n<=2||m<=2){puts("NO");return 0;} for(int i=2;i<n;i++) for(int j=2;j<m;j++) if(mp[i][j]=='*'&&mp[i-1][j]=='*'&&mp[i+1][j]=='*'&&mp[i][j-1]=='*'&&mp[i][j+1]=='*') { vis[i][j]=1; int k=i; while(k>1&&mp[k-1][j]=='*')vis[--k][j]=1; k=i; while(k<n&&mp[k+1][j]=='*')vis[++k][j]=1; k=j; while(k>1&&mp[i][k-1]=='*')vis[i][--k]=1; k=j; while(k<m&&mp[i][k+1]=='*')vis[i][++k]=1; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(!vis[i][j]&&mp[i][j]=='*'){puts("NO");return 0;} puts("YES"); return 0; } puts("NO"); }
C
首先要学会用vector<char>,然后每个串记录元音出现次数和最后的元音是什么,统计二者都相同的对数和只有一个相同的对数,直接贪心取。
#include<bits/stdc++.h> using namespace std; typedef pair<int,int>pii; const int N=1e5+7; int n,id[200]; vector<char>a[N]; vector<int>G[N*10][5]; vector<pii>v1,v2; char str[N*10]; void print(int x){for(int i=0;i<a[x].size();i++)printf("%c",a[x][i]);} int main() { scanf("%d",&n); memset(id,-1,sizeof id); id['a']=0,id['e']=1,id['o']=2,id['i']=3,id['u']=4; for(int i=1;i<=n;i++) { scanf("%s",str+1); int len=strlen(str+1),num=0,yid=0; for(int j=1;j<=len;j++) { a[i].push_back(str[j]); if(id[str[j]]!=-1)num++,yid=id[str[j]]; } G[num][yid].push_back(i); } for(int i=1;i<=1e6;i++) for(int j=0;j<5;j++) if(G[i][j].size()&&G[i][j].size()%2==0) { for(int k=0;k<G[i][j].size();k+=2)v1.push_back(pii(G[i][j][k],G[i][j][k+1])); G[i][j].clear(); } else if(G[i][j].size()) { int p=G[i][j][0]; for(int k=1;k<G[i][j].size();k+=2)v1.push_back(pii(G[i][j][k],G[i][j][k+1])); G[i][j].clear(); G[i][j].push_back(p); } for(int i=1;i<=1e6;i++) { int pre=-1; for(int j=0;j<5;j++) if(G[i][j].size()) { if(pre==-1)pre=j; else v2.push_back(pii(G[i][pre][0],G[i][j][0])),pre=-1; } } if(v1.size()<=v2.size()) { printf("%d ",v1.size()); for(int i=0;i<v1.size();i++) { print(v2[i].first),printf(" "),print(v1[i].first),puts(""); print(v2[i].second),printf(" "),print(v1[i].second),puts(""); } } else{ printf("%d ",v2.size()+(v1.size()-v2.size())/2); for(int i=0;i<v2.size();i++) { print(v2[i].first),printf(" "),print(v1[i].first),puts(""); print(v2[i].second),printf(" "),print(v1[i].second),puts(""); } for(int i=v2.size()+1;i<v1.size();i+=2) { print(v1[i-1].first),printf(" "),print(v1[i].first),puts(""); print(v1[i-1].second),printf(" "),print(v1[i].second),puts(""); } } }
D
这题太难了吧,调不出来早知道去hack B了……细节贼多……首先发现选取的位置不是在重心就是叶子节点,然后显然先判断重心是否可行,判断方法大家应该都会。然后发现每种深度的叶子只要判断一个节点即可,发现种类数多时在深度小的时候就会被判掉,于是写过了。
#include<bits/stdc++.h> using namespace std; const int N=1e5+7; int n,siz,rt,flag,sz[N],mp[N],a[N]; vector<int>G[N],vec[2]; void dfs(int u,int fa) { sz[u]=1; int mx=0; for(int i=0;i<G[u].size();i++)if(G[u][i]!=fa) dfs(G[u][i],u),sz[u]+=sz[G[u][i]],mx=max(mx,sz[G[u][i]]); mx=max(mx,n-sz[u]); if(mx<siz)siz=mx,rt=u; } void dfs1(int u,int fa,int dep) { if(!a[dep])a[dep]=G[u].size(); else if(a[dep]!=G[u].size())flag=1; sz[u]=1; for(int i=0;i<G[u].size();i++) if(G[u][i]!=fa)dfs1(G[u][i],u,dep+1),sz[u]+=sz[G[u][i]]; if(G[u].size()==1)mp[dep]=u; } bool solve() { flag=0; memset(a,0,sizeof a); for(int i=0;i<G[rt].size();i++)dfs1(G[rt][i],rt,1); if(flag)return 0; for(int i=1;i<G[rt].size();i++)if(sz[G[rt][i]]!=sz[G[rt][0]])return 0; return 1; } int main() { scanf("%d",&n); if(n<=3){puts("1");return 0;} siz=n; for(int i=1,x,y;i<n;i++)scanf("%d%d",&x,&y),G[x].push_back(y),G[y].push_back(x); dfs(1,0); if(solve()){printf("%d",rt);return 0;} for(int i=0;i<n;i++)if(mp[i]) { rt=mp[i]; if(solve()){printf("%d",rt);return 0;} } puts("-1"); }
E
显然考虑f1、f2、f3和c出现的幂次数,然后构造3个3*3的矩阵和1个5*5的矩阵,直接转移即可。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int mod=1e9+7,gloid=1e9+6; int ans,f1,f2,f3,c; struct mat{ int a[5][5]; void clear(){memset(a,0,sizeof a);} void init() { memset(a,0,sizeof a); for(int i=0;i<5;i++)a[i][i]=1; } void prepare() { memset(a,0,sizeof a); a[0][0]=a[0][1]=a[1][0]=a[1][2]=a[2][0]=1; } }A; int qpow(int a,int b) { int ret=1; while(b) { if(b&1)ret=1ll*ret*a%mod; a=1ll*a*a%mod,b>>=1; } return ret; } mat operator*(mat a,mat b) { mat c;c.clear(); for(int i=0;i<5;i++) for(int j=0;j<5;j++) for(int k=0;k<5;k++) c.a[i][j]=(c.a[i][j]+1ll*a.a[i][k]*b.a[k][j])%gloid; return c; } mat qpow(mat a,ll b) { mat ret;ret.init(); while(b) { if(b&1)ret=ret*a; a=a*a,b>>=1; } return ret; } int main() { ll n; cin>>n>>f1>>f2>>f3>>c; A.prepare(); A=qpow(A,n-3); ans=1ll*qpow(f1,A.a[2][0])*qpow(f2,A.a[1][0])%mod*qpow(f3,A.a[0][0])%mod; A.clear(); for(int i=0;i<4;i++)A.a[i][0]=1; A.a[0][1]=A.a[1][2]=A.a[3][3]=A.a[4][3]=A.a[4][4]=1; A=qpow(A,n-3); ans=1ll*ans*qpow(c,2ll*(A.a[3][0]+A.a[4][0])%gloid)%mod; cout<<ans; }
F
其实上就是要让值距离π/2更近,然后分成小于π/2的和大于π/2两类,对于每一类二分一下,找到最近的答案,然后用exgcd找到最小的位置即可。细节有点多很难讲的详细,具体见code吧。
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<ll,ll>pii; ll a,b,p,q; ll calc(ll a,ll b,ll c,ll n) { if(!n)return 0; ll ret=a/c*n*(n-1)/2+b/c*n; a%=c,b%=c; return ret+calc(c,(a*n+b)%c,a,(a*n+b)/c); } bool check1(ll mid) {return calc(2*p,3*q,2*q,b+1)-calc(2*p,3*q,2*q,a)>calc(2*p,3*q-mid-1,2*q,b+1)-calc(2*p,3*q-mid-1,2*q,a);} bool check2(ll mid) {return calc(2*p,3*q,2*q,b+1)-calc(2*p,3*q,2*q,a)-calc(2*p,3*q-mid,2*q,b+1)+calc(2*p,3*q-mid,2*q,a)<b-a+1;} void exgcd(ll a,ll b,ll&x,ll&y) { if(!b){x=1,y=0;return;} exgcd(b,a%b,y,x),y-=a/b*x; } ll find(ll t,ll mn) { t=t+q>>1; ll x,y,d;exgcd(p,q,x,y); x=(x%q+q)%q*t%q; if(x>=mn)return x; d=(mn-x-1)/q+1; return x+q*d; } int main() { int T;cin>>T; while(T--) { cin>>a>>b>>p>>q; ll d=__gcd(p,q),l,r,mid; p/=d,q/=d,l=0,r=2*q-1; while(l<r) { ll mid=l+r>>1; if(check1(mid))r=mid;else l=mid+1; } pii ans=pii(l,find(l,a)); l=0,r=2*q-1; while(l<r) { mid=l+r+1>>1; if(check2(mid))l=mid;else r=mid-1; } ans=min(ans,pii(2*q-l,find(l,a))); cout<<ans.second<<endl; } }
result:rank12 rating=1838(用新号打的)