2016 CCPC 长春 Solution

Posted dup4

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2016 CCPC 长春 Solution相关的知识,希望对你有一定的参考价值。

A - Hanzo vs. Genji

留坑。

 

B - Fraction

水。

技术分享图片
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 inline int gcd(int a, int b)
 5 {
 6     return b ? gcd(b, a % b) : a; 
 7 }
 8 
 9 int t, n;
10 int a[10], b[10];
11 
12 int main()
13 {
14     scanf("%d", &t);
15     for (int kase = 1; kase <= t; ++kase)
16     {
17         scanf("%d", &n);
18         for (int i = 1; i <= n; ++i) scanf("%d", a + i);
19         for (int i = 1; i <= n; ++i) scanf("%d", b + i);
20         int p = b[n], q = a[n];
21         for (int i = n - 1; i >= 1; --i)
22         {
23             int tq = a[i] * q + p; 
24             int tp = b[i] * q;
25             p = tp, q = tq;
26             int Gcd = gcd(p, q); p /= Gcd, q /= Gcd;
27         }
28         int Gcd = gcd(p, q); p /= Gcd, q /= Gcd;
29         printf("Case #%d: %d %d
", kase, p, q);
30     }
31     return 0;
32 }
View Code

 

C - Rotate String

留坑。

 

D - Triangle

水。

技术分享图片
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int fic[25];
 5 
 6 int t, n;
 7 
 8 int main()
 9 {
10     fic[0] = fic[1] = 1;
11     for (int i = 2; i <= 20; ++i) fic[i] = fic[i - 1] + fic[i - 2];
12     scanf("%d", &t);
13     for (int kase = 1; kase <= t; ++kase)
14     {
15         scanf("%d", &n);
16         int pos = upper_bound(fic + 1, fic + 21, n) - fic;
17         printf("Case #%d: %d
", kase, n - pos + 1);
18     }
19     return 0;
20 }
View Code

 

E - The Fastest Runner Ms. Zhang

留坑。

 

F - Harmonic Value Description

题意:有一个1-n的全排列,定义一个值$sum_{i = 1}^{i = n - 1} gcd(p_i, p_{i + 1})$ 求这个值第k大的数列

思路:首先相邻的奇数的gcd为1,相邻的偶数的gcd为2

分类讨论:k=1输出原序列

k为偶数,将k和2*k提前输出在按照原序列输出,提供的贡献就是k-1

k为奇数,将3开始的k-1个奇数提前,其他按照原序列输出,每个奇数的提前会导致左右的偶数产生贡献为2

技术分享图片
 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define N 10010
 6 
 7 int n, k;
 8 int arr[N];
 9 int vis[N];
10 
11 int main()
12 {
13     int t;
14     scanf("%d",&t);
15     for(int cas = 1; cas <= t; ++cas)
16     {
17         scanf("%d %d",&n, &k);
18         printf("Case #%d:", cas);
19         memset(vis, 0, sizeof vis);
20         if(k == 1)
21         {
22             for(int i = 1; i <= n; ++i) arr[i] = i;
23         }
24         else if(k % 2 == 0)
25         {
26             arr[1] = k;
27             arr[2] = 2 * k;
28             int cnt = 3;
29             for(int i = 1; i <= n; ++i)
30             {
31                 if(i == k || i == 2 * k) continue;
32                 arr[cnt++] = i;
33             }
34         }
35         else 
36         {
37             int cnt = 1;
38             int num = 3;
39             for(int i = 1; i < k; ++i)
40             {
41                 arr[cnt++] = num;
42                 vis[num] = 1;
43                 num += 2;
44             }
45             for(int i = 1; i <= n; ++i)
46             {
47                 if(vis[i]) continue;
48                 arr[cnt++] = i;
49             }
50         }
51         for(int i = 1;  i <= n; ++i) printf(" %d", arr[i]);
52         printf("
");
53     }
54     return 0;
55 }
View Code

 

G - Instability

留坑。

 

H - Sequence I

题意:给出$arr[]$和$brr[]$ 给出p 求有多少个q  满足 $a_q, a_{q + p}, a_{q + 2p}.....a_{q + (m - 1)p}$ 和$brr[]$ 能够匹配上

思路:多次KMP  注意求nx数组的时候,要用模板中的第一个,不知道为啥。

技术分享图片
 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define N 1000010
 6 
 7 int arr[N];
 8 int brr[N];
 9 
10 int n, m, p;
11 
12 inline void preKMP(int x[], int m, int kmpNext[])
13 {
14     int i, j;
15     j = kmpNext[0] = -1;
16     i = 0;
17     while(i < m)
18     {
19         while(-1 != j && x[i] != x[j]) j = kmpNext[j];
20         kmpNext[++i] = ++j;
21     }        
22 }
23 
24 int nxt[N];
25 
26 int KMP_count(int x[], int m, int y[], int n)
27 {
28     preKMP(x, m, nxt);
29     int ans = 0;
30     for(int k = 0; k < p; ++k)
31     {
32         int i = k, j = 0;
33         while(i < n)
34         {
35             while(j != -1 && y[i] != x[j]) j = nxt[j];
36             i += p;j++;
37             if(j >= m)
38             {
39                 ans++;
40                 j = nxt[j];
41             }
42         }    
43     }
44     return ans;
45 }
46 
47 int main()
48 {
49     int t;
50     scanf("%d", &t);
51     for(int cas = 1; cas <= t; ++cas)
52     {
53         scanf("%d %d %d",&n, &m, &p);
54         for(int i = 0; i < n; ++i) scanf("%d", arr + i);
55         for(int i = 0; i < m; ++i) scanf("%d", brr + i);
56         int ans = KMP_count(brr, m, arr, n);
57         printf("Case #%d: %d
", cas, ans);
58     }
59     return 0;
60 }
View Code

 

I - Sequence II

题意:给出一个$arr[]$ ,每次询问给出l, r  求这个区间内第一次出现的数中,第K个数的下标

思路:裸的主席树

技术分享图片
  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 
  4 #define N 200010
  5 #define M N * 50
  6 
  7 int t, n, q, ans;
  8 int vis[N], arr[N];
  9 int T[N], L[M], R[M], C[M], tot;
 10 
 11 inline int build(int l, int r)
 12 {
 13     int root = tot++;
 14     C[root] = 0;
 15     if (l < r)
 16     {
 17         int mid = (l + r) >> 1;
 18         L[root] = build(l, mid);
 19         R[root] = build(mid + 1, r);
 20     }
 21     return root;
 22 }
 23 
 24 inline int update(int root, int pos, int val)
 25 {
 26     int newroot = tot++, tmp = newroot;
 27     C[newroot] = C[root] + val;
 28     int l = 1, r = n;
 29     while (l < r)
 30     {
 31         int mid = (l + r) >> 1;
 32         if (pos <= mid)
 33         {
 34             L[newroot] = tot++, R[newroot] = R[root];
 35             newroot = L[newroot], root = L[root];
 36             r = mid;
 37         }
 38         else
 39         {
 40             L[newroot] = L[root], R[newroot] = tot++;
 41             newroot = R[newroot], root = R[root];
 42             l = mid + 1;
 43         }
 44         C[newroot] = C[root] + val;
 45     }
 46     return tmp;
 47 }
 48 
 49 inline int query(int root, int pos)
 50 {
 51     int l = 1, r = n;
 52     int res = 0;
 53     while (l < r)
 54     {
 55         int mid = (l + r) >> 1;
 56         if (pos <= mid)
 57         {
 58             root = L[root];
 59             r = mid;
 60         }
 61         else
 62         {
 63             res += C[L[root]];
 64             root = R[root];
 65             l = mid + 1;
 66         }
 67     }
 68     return res + C[root];
 69 }
 70 
 71 inline int query2(int root, int k)
 72 {
 73     int l = 1, r = n;
 74     int res = 0;
 75     while (l < r)
 76     {
 77         int mid = (l + r) >> 1;
 78         if (C[L[root]] >= k)
 79         {
 80             root = L[root];
 81             r = mid;
 82         }
 83         else
 84         {
 85             k -= C[L[root]];
 86             root = R[root];
 87             l = mid + 1;
 88         }
 89     }
 90     return l;
 91 
 92 }
 93 
 94 int main()
 95 {
 96     scanf("%d", &t);
 97     for (int kase = 1; kase <= t; ++kase)
 98     {
 99         printf("Case #%d:", kase);
100         scanf("%d%d", &n, &q); tot = 0; 
101         for (int i = 1; i <= n; ++i) scanf("%d", arr + i);
102         T[n + 1] = build(1, n); 
103         memset(vis, 0, sizeof vis);
104         for (int i = n; i >= 1; --i)
105         {
106             if (vis[arr[i]] == 0)
107             {
108                 T[i] = update(T[i + 1], i, 1);    
109             }
110             else
111             {
112                 T[i] = update(T[i + 1], vis[arr[i]], -1);
113                 T[i] = update(T[i], i, 1);
114             }
115             vis[arr[i]] = i;
116         }
117         ans = 0;
118         for (int i = 1, l, r; i <= q; ++i) 
119         {
120             scanf("%d%d", &l, &r);
121             l = (l + ans) % n + 1;
122             r = (r + ans) % n + 1;
123             if (l > r) swap(l, r);
124             if (l == r)
125             {
126                 printf(" %d", l);
127                 ans = l;
128                 continue;
129             }
130             int k = query(T[l], r); k = (k + 1) / 2;
131             ans = query2(T[l], k);
132             printf(" %d", ans);
133         }
134         puts("");
135     }
136     return 0;
137 }
View Code

 

J - Ugly Problem

题意:给出一个数,求这个数能够被多少个回文数相加得到,个数不能超过50,输出这些数

思路:如果是10000 这样的数,那么就取9999  否则 就是  位数减半的前一位-1然后右半部分回文得到回文数

技术分享图片
 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 int main() {
 6     int t;
 7     char st[10000];
 8     int a[10000],b[10000],ans[100][10000];
 9     int x,y;
10     int i,j,k,len,cnt,kase;
11     scanf("%d",&t);
12     kase=0;
13     while (t--) {
14         printf("Case #%d:
",++kase);
15         scanf("%s",st);
16         len=strlen(st);
17         for (i=0;i<len;++i)
18             a[len-i]=st[i]-48;
19         x=len;
20         cnt=0;
21         while (x>1) {
22             cnt++;
23             k=x/2+1;
24             memset(b,0,sizeof b);
25             while (k<=x) {
26                 if (a[k]==0) b[k]=9;
27                 else 
28                 {
29                     b[k]=a[k]-1;
30                     k++;
31                     break;
32                 }
33                 k++;
34             }
35             while (k<=x) {
36                 b[k]=a[k];
37                 k++;
38             }
39             y=x;
40             for (i=1;i<=x/2;++i)
41                 b[i]=b[y-i+1];
42             if (b[y]==0) {b[1]=9; y--;}
43             ans[cnt][0]=y;
44             for (i=y;i>=1;--i) {
45                 ans[cnt][i]=b[i];
46                 //printf("%d",b[i]);
47                 a[i]=a[i]-b[i];
48             }
49             //printf("
");
50             for (i=1;i<=x;++i)
51                 if (a[i]<0) {
52                     a[i]=a[i]+10;
53                     a[i+1]--;
54                 }
55             while (a[x]==0) --x;
56         }
57         if (a[1]!=0) {cnt++; ans[cnt][0]=1; ans[cnt][1]=a[1];}
58         printf("%d
",cnt);
59         for (i=1;i<=cnt;++i) {
60             for (j=ans[i][0];j>=1;--j) printf("%d",ans[i][j]);
61             printf("
");
62         }
63     }
64     return 0;
65 }
View Code

 

K - Binary Indexed Tree

留坑。

 

以上是关于2016 CCPC 长春 Solution的主要内容,如果未能解决你的问题,请参考以下文章

[2016CCPC]长春现场赛重现

2016中国大学生程序设计竞赛(ccpc 长春) Fraction模拟

2016中国大学生程序设计竞赛(ccpc 长春)题解报告

CCPC2016长春B (hdu 5912 Fraction)

CCPC2016长春D (hdu 5914 Triangle)

组队训练2016 CCPC 长春