The 2017 China Collegiate Programming Contest, Hangzhou Site Solution

A: Super_palindromec++

題面:給出一個字符串,求改變最少的字符個數使得這個串全部長度爲奇數的子串都是迴文串dom

思路:顯然,這個字符串確定要改爲全部奇數位相同而且全部偶數位相同ide

那統計一下奇數位上哪一個字符出現的個數最多,偶數位上哪一個字符出現的個數最多spa

答案就是 n 減去它們code

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define N 110
 6 #define INF 0x3f3f3f3f
 7 
 8 int t;
 9 char s[N];
10 
11 int odd[200];
12 int even[200];
13 
14 int main()
15 {
16     scanf("%d", &t);
17     while (t--)
18     {
19         scanf("%s", s);
20         memset(odd, 0, sizeof odd);
21         memset(even, 0, sizeof even);
22         int len = strlen(s);
23         int Maxodd = 0, Maxeven = 0;
24         for (int i = 0; i < len; ++i)
25         {
26             if (i & 1)
27                 odd[s[i]]++, Maxodd = max(Maxodd, odd[s[i]]);
28             else
29                 even[s[i]]++, Maxeven = max(Maxeven, even[s[i]]);
30         }
31         printf("%d\n", len - Maxodd - Maxeven);
32     }
33     return 0;
34 }
View Code

 

B: Master of Phiblog

題意:給定一個n,接下來n行輸入p和q表明數字num有q個p因子,計算題中式子字符串

思路:根據題中數字提取出公因數n,而後每一個式子只是每一個數的質因子乘上(1-1/p)。對於全部要求的式子,對於每一個質因子p僅可能0-q中可能,因此所求式子就變成了∏((1-1/pi)*qi+1)所得值。it

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define N 110
 6 
 7 typedef long long ll;
 8 
 9 const int MOD = 998244353;
10 
11 inline ll qpow(ll x,ll n)
12 {
13     ll res = 1;
14     while(n)
15     {
16         if(n & 1) res = (res * x) % MOD;
17         x = (x * x) % MOD;
18         n >>= 1;
19     }
20     return res;
21 }
22 
23 int m;
24 ll p[N],q[N];
25 ll tmp[N];
26 
27 int main()
28 {
29     int t;
30     scanf("%d",&t);
31     while(t--)
32     {
33         scanf("%d",&m);
34         ll ans = 1;
35         for(int i = 1;i <= m; ++i)
36         {
37             scanf("%lld %lld",&p[i], &q[i]);
38             p[i] %= MOD;
39             ans = (ans * qpow(p[i], q[i])) % MOD;
40             p[i] = (p[i] - 1) * qpow(p[i], MOD - 2) % MOD;
41             tmp[i] = p[i] * q[i] % MOD;
42         }
43         for(int i = 1; i <= m; ++i)
44         {
45             ans = (ans * (tmp[i] + 1) % MOD) % MOD;
46         }
47         printf("%lld\n",ans);
48     }
49     return 0;
50 }
View Code

 

 

 

C: Hakase and Nanoevent

題面:有n堆石子,兩我的輪流取,Hakase 一輪必須取兩次,另外一我的一輪取一次,最後取光的人勝利,給出前後手順序,判斷哪一個人必勝ast

思路:經過兩我的的簡單模擬,能夠發現Hakase的優點很大,它的必敗狀況不多。

如下四種爲必敗狀況

H先手,而且全部石子堆都是1,而且石子堆數%3==0

H後手,而且全部石子堆都是1,而且石子堆數%3==1

H後手,而且有一個石子堆的個數不是1,其它全是1,而且石子堆數%3==0 || %3 == 1

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define N 1000010
 6 
 7 int n, d;
 8 int arr[N];
 9 
10 int main()
11 {
12     int t;
13     scanf("%d",&t);
14     while(t--)
15     {
16         scanf("%d %d",&n,&d);
17         int num = 0;
18         for(int i = 1; i <= n; ++i)
19         {
20             scanf("%d",&arr[i]);
21             if(arr[i] > 1) num++;
22         }
23         if(num >= 2)
24         {
25             puts("Yes");
26             continue;
27         }
28         if(d == 1)
29         {
30             if(num == 0 && n % 3 == 0) puts("No");
31             else puts("Yes");
32         }
33         else if(d == 2)
34         {
35             if(num == 0 && n % 3 == 1) puts("No");
36             else if(num == 1 && (n % 3 == 0 || n % 3 == 1)) puts("No");
37             else puts("Yes");
38         }
39     }
40     return 0;
41 }
View Code

 

D:Master of Random

題意:給出一棵樹,每一個節點都有一個權值,對於第i個節點,它的father是random(0, i-1),求任意一顆子樹的權值指望。

題意:對於一顆子樹,它的權值爲自身權值加上除本身之外的權值指望。對於節點i,那麼i+1是節點i的子節點的機率爲1/(1 + i),對於第i+2個節點是節點i的子節點的機率爲1/(i+2)+1/(i+1)*1/(i+2)=1/(i+1),從而發現後面每一個節點是i的子節點的機率都爲1/(i+1)。那麼第i個節點的權值指望就爲ai+1/(i+1)*∑aj(j from i+1 to n-1)

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 typedef long long ll;
 6 
 7 const int MOD = 998244353;
 8 
 9 #define N 100010
10 
11 inline ll qpow(ll x,ll n)
12 {
13     ll res = 1;
14     while(n)
15     {
16         if(n & 1) res = (res * x) % MOD;
17         x = (x * x) % MOD;
18         n >>= 1;
19     }
20     return res;
21 }
22 
23 int n;
24 ll a[N];
25 ll sum[N];
26 
27 int main()
28 {
29     int t;
30     scanf("%d",&t);
31     while(t--)
32     {
33         scanf("%d",&n);
34         for(int i = 0;i < n; ++i)
35         {
36             scanf("%lld",&a[i]);
37         }
38         memset(sum, 0, sizeof sum);
39         for(int i = n - 1; i >= 0; --i)
40         {
41             sum[i] = (sum[i + 1] + a[i]) % MOD;
42         }
43         ll ans = 0;
44         for(int i = 0;i < n; ++i)
45         {
46             ans = (ans + (a[i] + sum[i + 1] * qpow(i + 1, MOD - 2) % MOD) % MOD) % MOD;
47         }
48         ans = (ans * qpow(n, MOD - 2)) % MOD;
49         printf("%lld\n", ans);
50     }
51     return 0;
52 }
View Code

 

 

 

E:Master of Subgraph

留坑。

 

F:Hearthock

留坑。

 

G:Marriage

留坑。

 

H:Master of Connexted Component

留坑。

 

I:Master of Matrix

留坑

 

J:Master of GCD

題意:有n個數剛開始都是1,而後每次操做使得(l, r)區間的全部數都乘上x,x == 2 || x ==3 求全部數的最大公約數

思路:顯然,咱們找出乘2最少的次數n,以及乘3最少的次數m 答案就是2^n * 3*m

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 typedef long long ll;
 6 const int INF = 0x3f3f3f3f;
 7 const int p = 998244353;
 8 #define N 100010
 9 
10 int n, m;
11 
12 ll sum_2[N], sum_3[N];
13 
14 ll qpow(ll x,ll n)
15 {
16     ll res = 1;
17     while(n)
18     {
19         if(n & 1) res = (res * x) %p;
20         x = (x * x) % p;
21         n >>= 1;
22     }
23     return res;
24 }
25 
26 int main()
27 {
28     int t;
29     scanf("%d",&t);
30     while(t--)
31     {
32         memset(sum_2, 0, sizeof sum_2);
33         memset(sum_3, 0, sizeof sum_3);
34         scanf("%d %d",&n,&m);
35         for(int i = 0; i < m; ++i)
36         {
37             int l,r,x;
38             scanf("%d %d %d",&l ,&r ,&x);
39             if(x == 2)
40             {
41                 sum_2[l]++;
42                 sum_2[r + 1]--;
43             }
44             else 
45             {
46                 sum_3[l]++;
47                 sum_3[r + 1]--;
48             }
49         }
50         ll Min_2 = INF;
51         ll Min_3 = INF;
52         ll op_2 = 0, op_3 = 0;
53         for(int i = 1; i <= n; ++i)
54         {
55             op_2 += sum_2[i];
56             Min_2 = min(Min_2, op_2);
57             op_3 += sum_3[i];
58             Min_3 = min(Min_3, op_3);
59         }
60         ll ans = 1;
61         ans = (ans * qpow(2, Min_2)) % p;
62         ans = (ans * qpow(3, Min_3)) % p;
63         printf("%lld\n",ans);
64     }    
65     return 0;
66 }
View Code

 

K:Master of Sequence

題意:兩組序列,三種操做。

思路:ai很小,咱們能夠考慮對ai做文章。能夠把那個式子拆開當作 floor(t / ai) - (bi / ai)

而後預處理出bi / ai 的整數部分和餘數部分 而且將全部整數部分相加獲得sum

而後查詢的時候二分枚舉t,查詢的時候用去考慮對於同一個ai, 若是t/ai 的餘數小於  bi/ai 的餘數 那就須要多減一 而後加上整數部分

而後前綴和處理一下,二分的時間複雜度爲logn * 1000

修改的時間複雜度爲O(1000)

  1 #include <bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 #define N 100010
  6 
  7 #define M 1010
  8 
  9 #define ll long long
 10 
 11 #define INFLL (ll)1e12
 12 
 13 int arr[N], brr[N];
 14 
 15 int a[M][M];
 16 
 17 ll sum;
 18 
 19 int n, m;
 20 
 21 inline bool check(ll mid, ll k)
 22 {
 23     ll tot = -sum;
 24     for (int i = 1; i <= 1000; ++i)
 25     {
 26         ll tmp = mid / i;
 27         ll MOD = mid % i;
 28         tot += tmp * a[i][0];
 29         tot -= a[i][MOD + 1];
 30     }
 31     return tot >= k;
 32 }
 33 
 34 int main()
 35 {
 36     int t; scanf("%d", &t);
 37     while (t--)
 38     {
 39         scanf("%d%d", &n, &m);
 40         for (int i = 1; i <= n; ++i)
 41             scanf("%d", arr + i);
 42         for (int i = 1; i <= n; ++i)
 43             scanf("%d", brr + i);
 44         memset(a, 0, sizeof a);
 45         sum = 0;
 46         for (int i = 1; i <= n; ++i)
 47         {
 48             a[arr[i]][brr[i] % arr[i]]++;
 49             sum += brr[i] / arr[i];
 50         }
 51         for (int i = 1; i <= 1000; ++i)
 52         {
 53             for (int j = 999; j >= 0; --j)
 54             {
 55                 a[i][j] += a[i][j + 1];
 56             }
 57         }
 58         int op, x, y, k;
 59         while (m--)
 60         {
 61             scanf("%d", &op);
 62             if (op == 1)
 63             {
 64                 scanf("%d%d", &x, &y);
 65                 int tmp = arr[x]; arr[x] = y;
 66                 for (int i = 0; i <= brr[x] % tmp; ++i)
 67                     a[tmp][i]--;
 68                 sum -= brr[x] / tmp;
 69                 sum += brr[x] / arr[x];
 70                 for (int i = 0; i <= brr[x] % arr[x]; ++i)
 71                     a[arr[x]][i]++;
 72             }
 73             else if (op == 2)
 74             {
 75                 scanf("%d%d", &x, &y);
 76                 int tmp = brr[x]; brr[x] = y;
 77                 for (int i = 0; i <= tmp % arr[x]; ++i)
 78                     a[arr[x]][i]--;
 79                 sum -= tmp / arr[x];
 80                 sum += brr[x] / arr[x];
 81                 for (int i = 0; i <= brr[x] % arr[x]; ++i)
 82                     a[arr[x]][i]++;
 83             }
 84             else if (op == 3)
 85             {
 86                 scanf("%d", &k);
 87                 ll l = 0, r = INFLL, ans = -1;
 88                 while (r - l >= 0)
 89                 {
 90                     ll mid = (l + r) >> 1;
 91                     if (check(mid, (ll)k))
 92                     {
 93                         ans = mid;
 94                         r = mid - 1;
 95                     }
 96                     else
 97                     {
 98                         l = mid + 1;
 99                     }
100                 }
101                 printf("%lld\n", ans);
102             }
103         }
104     }
105     return 0;
106 }
View Code

 

L:Mod, Xor and Everything

留坑。

相關文章
相關標籤/搜索