A:
gcd(a,b)==1为有限,否则无限
1 #include<bits/stdc++.h> 2 using namespace std; 3 int T; 4 int a,b; 5 int gcd(int a,int b) 6 { 7 if(!b)return a; 8 return gcd(b,a%b); 9 } 10 int main() 11 { 12 scanf("%d",&T); 13 while(T--) 14 { 15 scanf("%d%d",&a,&b); 16 if(gcd(a,b)!=1)puts("Infinite"); 17 else puts("Finite"); 18 } 19 }
B:
贪心地模拟一下
1 #include<bits/stdc++.h> 2 using namespace std; 3 int T,n,a,b,c; 4 char s[105],Ans[105]; 5 int main() 6 { 7 scanf("%d",&T); 8 while(T--) 9 { 10 scanf("%d%d%d%d",&n,&a,&b,&c); 11 scanf("%s",s+1); 12 memset(Ans,0,sizeof(Ans)); 13 int ans=0; 14 for(int i=1;i<=n;++i) 15 { 16 if(s[i]=='R'&&b>0)Ans[i]='P',b--,ans++; 17 if(s[i]=='P'&&c>0)Ans[i]='S',c--,ans++; 18 if(s[i]=='S'&&a>0)Ans[i]='R',a--,ans++; 19 } 20 if(ans>=(n+1)/2) 21 { 22 puts("YES"); 23 for(int i=1;i<=n;++i)if(!Ans[i]) 24 { 25 if(a)Ans[i]='R',a--; 26 else if(b)Ans[i]='P',b--; 27 else Ans[i]='S',c--; 28 } 29 printf("%s ",Ans+1); 30 } 31 else puts("NO"); 32 } 33 }
C:
先判一下有w或者m为0
发现每个u和n形成的连续段答案可以递推,递推式为斐波拉契
然后预处理斐波拉契取出所有连续段,方案数相乘
1 #include<bits/stdc++.h> 2 #define maxn 100005 3 using namespace std; 4 const int mod = 1000000007; 5 int n; 6 char s[maxn]; 7 vector<int> A; 8 int dp[maxn]; 9 int main() 10 { 11 scanf("%s",s+1); 12 n=strlen(s+1); 13 dp[0]=dp[1]=1; 14 for(int i=1;i<=n;++i)dp[i]=(dp[i-1]+dp[i-2])%mod; 15 for(int i=1;i<=n;++i)if(s[i]=='w'||s[i]=='m'){puts("0");return 0;} 16 int len=0; 17 for(int i=1;i<=n;++i) 18 { 19 if(s[i]=='u') 20 { 21 if(s[i-1]=='u')len++; 22 else 23 { 24 if(len)A.push_back(len); 25 len=1; 26 } 27 } 28 else if(s[i]=='n') 29 { 30 if(s[i-1]=='n')len++; 31 else 32 { 33 if(len)A.push_back(len); 34 len=1; 35 } 36 } 37 else 38 { 39 if(len)A.push_back(len); 40 len=0; 41 } 42 } 43 if(len)A.push_back(len); 44 int ans=1; 45 for(auto len: A)ans=1ll*ans*dp[len]%mod; 46 printf("%d ",ans); 47 }
D:
超级根向每个点连边,权值为c[i]
点与点之间连边,权值为(k[i]+k[j])*dis(i,j)
最小生成树
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define maxn 2005 4 using namespace std; 5 int n; 6 ll X[maxn],Y[maxn],c[maxn],k[maxn]; 7 struct edge 8 { 9 int u,v; 10 ll w; 11 edge(int U=0,int V=0,ll W=0):u(U),v(V),w(W){} 12 }e[maxn*maxn]; 13 int fa[maxn]; 14 bool operator < (edge A,edge B){return A.w<B.w;} 15 int find(int x) 16 { 17 if(fa[x]==x)return x; 18 return fa[x]=find(fa[x]); 19 } 20 vector<int> A; 21 vector< pair<int,int> >B; 22 int main() 23 { 24 scanf("%d",&n); 25 for(int i=1;i<=n;++i)scanf("%I64d%I64d",&X[i],&Y[i]); 26 for(int i=1;i<=n;++i)scanf("%I64d",&c[i]); 27 for(int i=1;i<=n;++i)scanf("%I64d",&k[i]); 28 int cnt=0; 29 for(int i=0;i<=n;++i)fa[i]=i; 30 for(int i=1;i<=n;++i)e[++cnt]=edge(0,i,c[i]); 31 for(int i=1;i<=n;++i) 32 for(int j=1;j<=n;++j)if(i!=j)e[++cnt]=edge(i,j,(k[i]+k[j])*(abs(X[i]-X[j])+abs(Y[i]-Y[j]))); 33 sort(e+1,e+cnt+1); 34 ll ans=0; 35 for(int i=1;i<=cnt;++i) 36 { 37 int u=e[i].u,v=e[i].v; 38 if(find(u)==find(v))continue; 39 fa[find(v)]=find(u); 40 ans+=e[i].w; 41 if(!u)A.push_back(v); 42 else B.push_back(make_pair(u,v)); 43 } 44 printf("%I64d ",ans); 45 printf("%d ",A.size()); 46 for(auto p: A)printf("%d ",p); 47 puts(""); 48 printf("%d ",B.size()); 49 for(auto p: B)printf("%d %d ",p.first,p.second); 50 51 }
E:
期望DP
预处理出来每个位置的下一步是哪个点
然后记忆化搜一下就好了
1 #include<bits/stdc++.h> 2 using namespace std; 3 int a[12][12]; 4 double dp[12][12]; 5 bool vis[12][12]; 6 int nx[12][12],ny[12][12]; 7 double dfs(int x,int y) 8 { 9 if(vis[x][y])return dp[x][y]; 10 vis[x][y]=1; 11 if(x==1&&y==1)return dp[x][y]=0; 12 double res=0; 13 int px=x,py=y; 14 int num=6; 15 for(int k=1;k<=6;++k) 16 { 17 int xx=nx[px][py],yy=ny[px][py]; 18 px=xx;py=yy; 19 if(!px||!py)--num; 20 else res+=min(dfs(px,py),dfs(px-a[px][py],py))/6.0; 21 } 22 dp[x][y]=(res+1.0)*6.0/(double)num; 23 return dp[x][y]; 24 } 25 int main() 26 { 27 for(int i=1;i<=10;++i) 28 for(int j=1;j<=10;++j)cin>>a[i][j]; 29 for(int i=10;i>=1;--i) 30 { 31 if(i&1) 32 { 33 for(int j=10;j>=2;--j)nx[i][j]=i,ny[i][j]=j-1; 34 nx[i][1]=i-1;ny[i][1]=1; 35 } 36 else 37 { 38 for(int j=1;j<=9;++j)nx[i][j]=i,ny[i][j]=j+1; 39 nx[i][10]=i-1;ny[i][10]=10; 40 } 41 } 42 for(int i=1;i<=10;++i) 43 for(int j=1;j<=10;++j)dp[i][j]=1e9; 44 printf("%.10f ",dfs(10,1)); 45 }
F:
数位DP
先把问题容斥成(1,n,1,m)的形式
然后考虑状态为dp(len,0/1,0/1,lim1,lim2):在第len位,第一个是0/1,第二个是0/1,第一个贴不贴上界,第二个贴不贴上界
然后 a xor b = a+b就是每位都不产生进位
那么不能出现1 1这种情况
dp一下就好了
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 int T; 5 ll l,r; 6 ll a[35],b[35]; 7 ll fastpow(ll a,ll p) 8 { 9 ll ans=1; 10 while(p) 11 { 12 if(p&1)ans=ans*a; 13 a=a*a;p>>=1; 14 } 15 return ans; 16 } 17 ll dp[35][2][2][2][2]; 18 bool vis[35][2][2][2][2]; 19 ll dfs(ll len,ll x,ll y,ll lim1,ll lim2) 20 { 21 if(!len)return 1; 22 if(vis[len][x][y][lim1][lim2])return dp[len][x][y][lim1][lim2]; 23 vis[len][x][y][lim1][lim2]=1; 24 ll res=0; 25 if(a[len-1]==1&&b[len-1]==1) 26 { 27 res+=dfs(len-1,0,1,0,lim2)+dfs(len-1,1,0,lim1,0)+dfs(len-1,0,0,0,0); 28 } 29 else if(a[len-1]==1) 30 { 31 res+=dfs(len-1,0,0,0,lim2)+dfs(len-1,1,0,lim1,lim2); 32 if(!lim2)res+=dfs(len-1,0,1,0,0); 33 } 34 else if(b[len-1]==1) 35 { 36 res+=dfs(len-1,0,0,lim1,0)+dfs(len-1,0,1,lim1,lim2); 37 if(!lim1)res+=dfs(len-1,1,0,0,0); 38 } 39 else 40 { 41 res+=dfs(len-1,0,0,lim1,lim2); 42 if(!lim1)res+=dfs(len-1,1,0,0,lim2); 43 if(!lim2)res+=dfs(len-1,0,1,lim1,0); 44 } 45 return dp[len][x][y][lim1][lim2]=res; 46 } 47 ll solve(ll x,ll y) 48 { 49 memset(a,0,sizeof(a)); 50 memset(b,0,sizeof(b)); 51 memset(dp,0,sizeof(dp)); 52 memset(vis,0,sizeof(vis)); 53 for(int i=30;i>=0;--i)a[i]=(x>>i)&1,b[i]=(y>>i)&1; 54 ll ans=dfs(31,0,0,1,1); 55 return ans; 56 } 57 int main() 58 { 59 cin>>T; 60 while(T--) 61 { 62 cin>>l>>r; 63 if(l>0)cout<<solve(r,r)-solve(r,l-1)-solve(l-1,r)+solve(l-1,l-1)<<endl; 64 else cout<<solve(r,r)<<endl; 65 } 66 }