codeforces #597(div 2)

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     }
View Code

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\n",Ans+1);
30             }
31             else puts("NO");
32         }
33     }
View Code

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\n",ans);
47     }
View Code

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\n",ans);
45         printf("%d\n",A.size());
46         for(auto p: A)printf("%d ",p);
47         puts("");
48         printf("%d\n",B.size());
49         for(auto p: B)printf("%d %d\n",p.first,p.second);
50         
51     }
View Code

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\n",dfs(10,1));
45     }
View Code

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     }
View Code

猜你喜欢

转载自www.cnblogs.com/uuzlove/p/11780601.html