Codeforces Round #369 (Div. 2)

Problem A Bus to Udayland

题目大意

  公交车上有些位置能做,有些不能坐,问是否有两个相邻的位置。

解题分析

  找到并列的两个O就行。

参考程序

 1 #include <map>
 2 #include <set>
 3 #include <stack>
 4 #include <queue>
 5 #include <cmath>
 6 #include <ctime>
 7 #include <string>
 8 #include <vector>
 9 #include <cstdio>
10 #include <cstdlib>
11 #include <cstring>
12 #include <cassert>
13 #include <iostream>
14 #include <algorithm>
15 #pragma comment(linker,"/STACK:102400000,102400000")
16 using namespace std;
17 
18 #define N 508             
19 #define M 50008    
20 #define LL long long
21 #define lson l,m,rt<<1
22 #define rson m+1,r,rt<<1|1 
23 #define clr(x,v) memset(x,v,sizeof(x));
24 #define bitcnt(x) __builtin_popcount(x)
25 #define rep(x,y,z) for (int x=y;x<=z;x++)
26 #define repd(x,y,z) for (int x=y;x>=z;x--)
27 const int mo  = 1000000007;
28 const int inf = 0x3f3f3f3f;
29 const int INF = 2000000000;
30 /**************************************************************************/ 
31 int n;
32 char s[1008][10];
33 int main(){
34     scanf("%d",&n);
35     rep(i,1,n) scanf("%s",s[i]);
36     int flag=0;
37     rep(i,1,n){
38         if (s[i][0]=='O' && s[i][1]=='O'){
39             s[i][0]=s[i][1]='+';
40             flag=1;
41             break;
42         }
43 
44         if (s[i][3]=='O' && s[i][4]=='O'){
45             s[i][3]=s[i][4]='+';
46             flag=1;
47             break;
48         }
49     }
50     if (flag){
51         printf("YES\n");
52         rep(i,1,n) puts(s[i]);
53     }
54     else printf("NO\n");
55 }
View Code

 

Problem B Chris and Magic Square

题目大意

  一个n*n(n<=500)的矩形中有一个格子为空,问是否能填上某个数,使得每行每列以及主对角线之后均相等。

解题分析

  n=1特判。n>=2找出某个可能合法的解,填入后再验证一下。 记得开long long。

参考程序

 1 #include <map>
 2 #include <set>
 3 #include <stack>
 4 #include <queue>
 5 #include <cmath>
 6 #include <ctime>
 7 #include <string>
 8 #include <vector>
 9 #include <cstdio>
10 #include <cstdlib>
11 #include <cstring>
12 #include <cassert>
13 #include <iostream>
14 #include <algorithm>
15 #pragma comment(linker,"/STACK:102400000,102400000")
16 using namespace std;
17 
18 #define N 508             
19 #define M 50008    
20 #define LL long long
21 #define lson l,m,rt<<1
22 #define rson m+1,r,rt<<1|1 
23 #define clr(x,v) memset(x,v,sizeof(x));
24 #define bitcnt(x) __builtin_popcount(x)
25 #define rep(x,y,z) for (int x=y;x<=z;x++)
26 #define repd(x,y,z) for (int x=y;x>=z;x--)
27 const int mo  = 1000000007;
28 const int inf = 0x3f3f3f3f;
29 const int INF = 2000000000;
30 /**************************************************************************/ 
31 
32 int n,x,y;
33 LL a[1008][1008];
34 LL work(){
35     LL sum=0;
36     rep(i,1,n) if (i!=x)
37     {
38         rep(j,1,n) sum+=a[i][j];
39         break;
40     }
41     LL op=0;
42     LL cnt=0;
43     rep(j,1,n) cnt+=a[x][j];
44     op=sum-cnt;
45     a[x][y]=op;
46     if (op<=0) return -1;
47     rep(i,1,n) 
48     {
49         cnt=0;
50         rep(j,1,n) cnt+=a[i][j];
51         if (cnt!=sum) return -1;
52     }
53     rep(j,1,n) 
54     {
55         cnt=0;
56         rep(i,1,n) cnt+=a[i][j];
57         if (cnt!=sum) return -1;
58     }
59     cnt=0;
60     rep(i,1,n) cnt+=a[i][i];
61     if (cnt!=sum) return -1;
62 
63     cnt=0;
64     rep(i,1,n) cnt+=a[i][n-i+1];
65     if (cnt!=sum) return -1;    
66 
67     return op; 
68 
69 
70 }
71 int main(){
72     scanf("%d",&n);
73     rep(i,1,n) rep(j,1,n) 
74     {
75         scanf("%d",&a[i][j]);
76         if (a[i][j]==0) { x=i; y=j; }
77     }
78     if (n==1)
79     {
80         printf("1\n");
81         return 0;
82     }
83     printf("%I64d\n",work());
84 }
View Code

 

Problem C Coloring Trees

题目大意

  有n棵树排成一列,一共有m种颜料,有些树被涂了颜色,有些树没有。

  可以花费a[i][j]的代价给第i棵树涂上j的颜色。

  问给每棵树涂上颜色后,将树恰好分成k段的最小花费。(连续颜色相同的最长区间为一段)

  n,m,k<=100

解题分析

  只想了个n^4的DP。。还有n^3的做法。

  dp[i][j][k]表示做到第i棵树,分成了j段,第i-1棵树的颜色为k。

  之后枚举第i棵树的颜色转移即可。

参考程序

 1 #include <map>
 2 #include <set>
 3 #include <stack>
 4 #include <queue>
 5 #include <cmath>
 6 #include <ctime>
 7 #include <string>
 8 #include <vector>
 9 #include <cstdio>
10 #include <cstdlib>
11 #include <cstring>
12 #include <cassert>
13 #include <iostream>
14 #include <algorithm>
15 #pragma comment(linker,"/STACK:102400000,102400000")
16 using namespace std;
17 
18 #define N 508             
19 #define M 50008    
20 #define LL long long
21 #define lson l,m,rt<<1
22 #define rson m+1,r,rt<<1|1 
23 #define clr(x,v) memset(x,v,sizeof(x));
24 #define bitcnt(x) __builtin_popcount(x)
25 #define rep(x,y,z) for (int x=y;x<=z;x++)
26 #define repd(x,y,z) for (int x=y;x>=z;x--)
27 const int mo  = 1000000007;
28 const int inf = 0x3f3f3f3f;
29 const LL INF = 2000000000000000ll;
30 /**************************************************************************/ 
31 
32 int n,m,len;
33 LL dp[108][108][108];
34 LL cost[108][108];
35 int c[108]; 
36 
37 void up(LL &x,LL y){
38     x = min(x,y);
39 }
40 int main(){
41     rep(i,0,100) rep(j,0,100) rep(k,0,100) dp[i][j][k]=INF; 
42     scanf("%d%d%d",&n,&m,&len);
43     rep(i,1,n) scanf("%d",&c[i]);
44     rep(i,1,n) rep(j,1,m) scanf("%I64d",&cost[i][j]);
45     dp[0][1][0]=0;
46     rep(i,0,n-1) rep(j,1,len) rep(k,0,m)
47     {
48         if (dp[i][j][k]!=INF)
49         {
50             if (c[i+1]==0)
51             {
52                 rep(col,1,m) if (col!=k)
53                 {
54                     if (k!=0) up(dp[i+1][j+1][col],dp[i][j][k]+cost[i+1][col]);
55                     if (k==0) up(dp[i+1][j][col],dp[i][j][k]+cost[i+1][col]);
56                 }
57                 if (k!=0) up(dp[i+1][j][k],dp[i][j][k]+cost[i+1][k]);
58             }
59             else
60             {
61                 if (c[i+1]==k || k==0)
62                 {
63                     up(dp[i+1][j][c[i+1]],dp[i][j][k]);
64                 }
65                 if (c[i+1]!=k && k!=0)
66                 {
67                     up(dp[i+1][j+1][c[i+1]],dp[i][j][k]);
68                 }
69             }
70         }            
71     }
72   /*  rep(i,0,n) rep(j,1,len) rep(k,0,m)
73         if (dp[i][j][k]!=INF)
74             printf("%d %d %d %I64d\n",i,j,k,dp[i][j][k] );*/
75     LL ans=INF;
76     rep(k,1,m) up(ans,dp[n][len][k]);
77     printf("%I64d\n",ans==INF ?-1 :ans);
78 }
View Code

 

Problem D Directed Roads

题目大意

  有n个点,给定一个数组a[i](≠i),表示有一条i-->a[i]的有向边。

  可以将某些有向边的方向翻转,因此共有2^n的方案。

  问这些方案中有多少种方案使得所形成的图不含有环。

  n<=2*10^5

解题分析

  由于一共只有n条边,整个图相当于被分成了若干个联通块,且每个联通块内有且只有一个环。

  若某个连通块中有i个点,存在一个点数为j的环,那么其对答案的贡献为2^(i-j) * (2^j-2)

参考程序

 1 #include <map>
 2 #include <set>
 3 #include <stack>
 4 #include <queue>
 5 #include <cmath>
 6 #include <ctime>
 7 #include <string>
 8 #include <vector>
 9 #include <cstdio>
10 #include <cstdlib>
11 #include <cstring>
12 #include <cassert>
13 #include <iostream>
14 #include <algorithm>
15 #pragma comment(linker,"/STACK:102400000,102400000")
16 using namespace std;
17 
18 #define N 200008            
19 #define M 400008    
20 #define LL long long
21 #define lson l,m,rt<<1
22 #define rson m+1,r,rt<<1|1 
23 #define clr(x,v) memset(x,v,sizeof(x));
24 #define bitcnt(x) __builtin_popcount(x)
25 #define rep(x,y,z) for (int x=y;x<=z;x++)
26 #define repd(x,y,z) for (int x=y;x>=z;x--)
27 const int mo  = 1000000007;
28 const int inf = 0x3f3f3f3f;
29 const int INF = 2000000000;
30 /**************************************************************************/ 
31 
32 int n,num,huan;
33 int a[N],mi[N+5],vis[N],len[N];
34 struct line{
35     int u,v,nt;
36 }eg[M];
37 int lt[N],sum;
38 
39 void add(int u,int v){
40     eg[++sum]=(line){u,v,lt[u]};
41     lt[u]=sum;
42 }
43 
44 void dfs(int u,int fa)
45 {
46     vis[u]=1; len[u]=len[fa]+1; num++;
47     for (int i=lt[u];i;i=eg[i].nt)
48     {
49         int v=eg[i].v;  
50         if (vis[v]==0)
51         {
52             dfs(v,u);
53         }
54         else
55         {
56             if (v!=fa)
57             {
58                 huan=abs(len[u]-len[v])+1;
59             }
60         }
61     }
62 }
63 
64 int main(){
65     mi[0]=1;
66     rep(i,1,N) mi[i]=1ll*mi[i-1]*2 % mo;
67     scanf("%d",&n);
68     rep(i,1,n)
69     {
70         scanf("%d",&a[i]);
71         add(i,a[i]);
72         add(a[i],i);
73     }
74     clr(vis,0);
75     LL ans=1;
76     rep(i,1,n) if (vis[i]==0)
77     {
78         num=0; huan=0;
79         dfs(i,0);
80         if (num==2) huan=2;
81         ans = (ans * (mi[huan]-2) % mo * mi[num-huan] % mo);
82     }
83     printf("%I64d\n",ans);
84 
85 }
View Code

 

Problem E ZS and The Birthday Paradox

题目大意

  假设一年有2^n天,问k个小朋友中有两个小朋友生日相同的概率。

  假设该概率约分后为 p / q ,输出p , q对1000003取模的解。

  n , k <= 10^18。

解题分析

  若k > 2^n 则答案为1 / 1 , 否则答案为 1 - A(2^n,k) / (2^n)^k , 

  可以发现分子与分母的gcd必定为2^i。

  计算A(2^n,k)=(2^n) * (2^n-1) * ... * (2^n-k+1)含多少个因子2,相当于计算0~k-1以及2^n。

  求出gcd后,就可以暴力计算分子,分母对p取模后的结果,再乘上gcd的逆元。

参考程序

 1 #include <map>
 2 #include <set>
 3 #include <stack>
 4 #include <queue>
 5 #include <cmath>
 6 #include <ctime>
 7 #include <string>
 8 #include <vector>
 9 #include <cstdio>
10 #include <cstdlib>
11 #include <cstring>
12 #include <cassert>
13 #include <iostream>
14 #include <algorithm>
15 #pragma comment(linker,"/STACK:102400000,102400000")
16 using namespace std;
17 
18 #define N 508             
19 #define M 50008    
20 #define LL long long
21 #define lson l,m,rt<<1
22 #define rson m+1,r,rt<<1|1 
23 #define clr(x,v) memset(x,v,sizeof(x));
24 #define bitcnt(x) __builtin_popcount(x)
25 #define rep(x,y,z) for (int x=y;x<=z;x++)
26 #define repd(x,y,z) for (int x=y;x>=z;x--)
27 const int mo  = 1000003;
28 const int inf = 0x3f3f3f3f;
29 const int INF = 2000000000;
30 /**************************************************************************/ 
31 LL n,k,num;
32 LL quick(LL x,LL y)
33 {
34     LL res=1;
35     while (y)
36     {
37         if (y & 1) res = res*x % mo;
38         x=x*x % mo;
39         y>>=1;
40     }
41     return res;
42 }
43 int main(){
44     scanf("%I64d%I64d",&n,&k);
45     if (n<=60 && k>(1ll<<n)){
46         printf("1 1\n");
47         return 0;
48     }
49     for (LL kk=k-1;kk;kk/=2) num+=kk/2;
50     LL tmp=quick(2,n),ans=1;
51     rep(i,1,k-1){
52         ans = ans * (--tmp) % mo; 
53         if (tmp==0) break;
54     }
55     ans=ans*quick(quick(2,mo-2),num) % mo;
56     LL ans1=quick(quick(2,n),k-1);
57     ans1=ans1*quick(quick(2,mo-2),num) % mo;
58     ans=ans1-ans;
59     if (ans<0) ans+=mo;
60     printf("%I64d %I64d\n",ans,ans1);
61 
62 }
View Code

 

posted @ 2016-08-30 10:49  rpSebastian  阅读(462)  评论(0编辑  收藏  举报