首页 > 代码库 > [2016CCPC]长春现场赛重现

[2016CCPC]长春现场赛重现

1002.公式,手算一下就能找到两个式子的关系,迭代一下就行。

技术分享
 1 #include <bits/stdc++.h> 2 using namespace std; 3  4 const int maxn = 9; 5 int a[maxn], b[maxn]; 6 int n, p, q; 7  8 int gcd(int x, int y) { 9   return y == 0 ? x : gcd(y, x%y);10 }11 12 int main() {13   //freopen("in", "r", stdin);14   int T, _ = 1;15   scanf("%d", &T);16   while(T--) {17     printf("Case #%d: ", _++);18     scanf("%d", &n);19     for(int i = 1; i <= n; i++) scanf("%d", &a[i]);20     for(int i = 1; i <= n; i++) scanf("%d", &b[i]);21     p = b[n], q = a[n];22     int t;23     for(int i = n-1; i >= 1; i--) {24       int tp = b[i] * q;25       int tq = a[i] * q + p;26       p = tp; q = tq;27       t = gcd(p, q);28       p /= t; q /= t;29     }30     t = gcd(p, q);31     p /= t; q /= t;32     printf("%d %d\n", p, q);33   }34   return 0;35 }
1002

1004.枚举所有情况打了一个表。

技术分享
 1 #include <bits/stdc++.h> 2 using namespace std; 3  4 const int maxn = 22; 5 int n, cnt; 6 int a[maxn]; 7 vector<int> tmp, ret; 8 bool ok(int a, int b, int c) { 9   return a + b > c;10 }11 void table() {12   while(~scanf("%d", &n)) {13     if(n <= 3) {14       printf("0\n");15       continue;16     }17     cnt = n;18     for(int i = 0; i < maxn; i++) a[i] = i;19     int nn = 1 << n;20     for(int i = 0; i < nn; i++) {21       tmp.clear();22       for(int j = 0; j < n; j++) {23         if((1 << j) & i) {24           tmp.push_back(j+1);25         }26       }27       int mm = 1 << tmp.size();28       bool flag = 0;29       for(int j = 0; j < mm; j++) {30         ret.clear();31         for(int k = 0; k < tmp.size(); k++) {32           if((1 << k) & j) {33             ret.push_back(tmp[k]);34           }35         }36         if(ret.size() == 3) {37           sort(ret.begin(), ret.end());38           if(ok(ret[0],ret[1],ret[2])) flag = 1;39         }40       }41       if(!flag) cnt = min(cnt, n-(int)tmp.size());42     }43     printf("%d\n", cnt);44   }45 }46 47 int fk[25]={0,0,0,0,1,1,2,3,3,4,5,6,7,7,8,9,10,11,12,13,14};48 49 int main() {50 //  freopen("in", "r", stdin);51   int T, _ = 1;52   scanf("%d", &T);53   while(T--) {54     scanf("%d", &n);55     printf("Case #%d: %d\n", _++, fk[n]);56   }57 }
1004

1006.有一个很!@#的条件就是1<=2k<=n,这样的话最多的情况就是偶数连在一起,这时候和谐值正好是n/2。构造前半段是奇数后半段是偶数,然后看看多了几个数,用奇数把偶数隔开就行了。

技术分享
 1 #include <bits/stdc++.h> 2 using namespace std; 3  4 const int maxn = 11110; 5 int a[maxn]; 6 int n, k; 7  8 int main() { 9   // freopen("in", "r", stdin);10   int T, _ = 1;11   scanf("%d", &T);12   while(T--) {13     scanf("%d %d", &n, &k);14     k--;15     printf("Case #%d: ", _++);16     int x = 0, y = 1;17     for(int i = 1; i <= k + 1; i++) {18       x += 2;19       a[i] = x;20     }21     for(int i = k + 2; i <= n; i++) {22       if(x > y) {23         a[i] = y;24         y += 2;25       }26       else a[i] = y++;27     }28     for(int i = 1; i <= n; i++) printf("%d%c", a[i], i==n?\n: );29   }30   return 0;31 }
1006

1007.Ramsey定理,我的思路是找到这个图的所有团,然后挨个组合一遍。看看一共有多少种。没

 

1008.仔细考虑一下复杂度就会明白,不管如何匹配,时间都不会到达O(n^2),所以不用kmp,直接暴力就行了。

技术分享
 1 #include <bits/stdc++.h> 2 using namespace std; 3  4 const int maxn = 1001000; 5 int a[maxn], b[maxn]; 6 int n, m, p; 7  8 int main() { 9 //  freopen("in", "r", stdin);10   int T, _ = 1;11   scanf("%d", &T);12   while(T--) {13     scanf("%d%d%d",&n,&m,&p);14     for(int i = 1; i <= n; i++) scanf("%d", &a[i]);15     for(int i = 1; i <= m; i++) scanf("%d", &b[i]);16     int ret = 0;17     for(int i = 1; i <= n; i++) {18       bool flag = 0;19       for(int j = 1; j <= m; j++) {20         if((i + (j - 1) * p > n) || (a[i+(j-1)*p] != b[j])) {21           flag = 1;22           break;23         }24       }25       if(!flag) ret++;26     }27     printf("Case #%d: %d\n", _++, ret);28   }29   return 0;30 }
1008
1009.主席树+二分。
技术分享
 1 #include<bits/stdc++.h> 2 using namespace std; 3  4 const int maxn = 200010; 5 int n,q,Case; 6 int a[maxn]; 7 typedef struct Node { 8     int l,r,sum; 9 }Node;10 Node tree[maxn*100];11 int rt[maxn],tot;12 void build(int &x,int l,int r) {13     x=++tot;tree[x].sum=0;14     if(l==r)return;15     int mid = (l + r) >> 1;16     build(tree[x].l,l,mid);17     build(tree[x].r,mid+1,r);18 }19 void update(int l,int r,int pos,int v,int y,int &x) {20     x=++tot;tree[x]=tree[y];tree[x].sum+=v;21     if(l==r)return;22     int mid = (l + r) >> 1;23     if(pos<=mid)update(l,mid,pos,v,tree[y].l,tree[x].l);24     else update(mid+1,r,pos,v,tree[y].r,tree[x].r);25 }26 int query(int t,int x,int l,int r) {27     if(l==r)return tree[t].sum;28     int mid = (l + r) >> 1;29     if(x<=mid)return query(tree[t].l,x,l,mid)+tree[tree[t].r].sum;30     return query(tree[t].r,x,mid+1,r);31 }32 33 int main() {34     // freopen("in","r",stdin);35     int T, _ = 1;36     scanf("%d",&T);37     while(T--) {38         scanf("%d%d",&n,&q);39         map<int,int>h;40         for(int i=1;i<=n;i++) {41             scanf("%d",&a[i]);42         }43         tot=0;build(rt[0],1,n);44         for(int i=1;i<=n;i++) {45             if(!h.count(a[i])) {46                 update(1,n,i,1,rt[i-1],rt[i]);47             }48             else {49                 update(1,n,h[a[i]],-1,rt[i-1],rt[i]);50                 update(1,n,i,1,rt[i],rt[i]);51             }52             h[a[i]]=i;53         }54         int ret=0;55         printf("Case #%d:", _++);56         while(q--) {57             int tl,tr;58             scanf("%d%d",&tl,&tr);59             tl=(tl+ret)%n+1,    tr=(tr+ret)%n+1;60             int l=min(tl,tr), r=max(tl,tr);61             int num=query(rt[r],l,1,n);62             int k=(num+1)/2;63             if(k<=1) {64                 ret=l;printf(" %d",ret);65                 continue;66             }67             int x = l, mid;68             while(l <= r) {69                 mid = (l + r) / 2;70                 int tmp = query(rt[mid],x,1,n);71                 if(tmp >= k) {72                     ret = mid;73                     r = mid - 1;74                 }75                 else l = mid + 1;76             }77             printf(" %d",ret);78         }79         puts("");80     }81     return 0;82 }
1009

 

1010.构造,无脑取前半段减一,然后对称地复制过去,这样被减数每次这么减总会剪掉一半的长度。我的实现需要特别注意一个情况就是10的时候直接给出结果就行了,否则会无限给出00。

技术分享
 1 #include <bits/stdc++.h> 2 using namespace std; 3  4 const int maxn = 1100; 5 char s[maxn]; 6 char t[maxn], r[maxn]; 7 vector<string> ret; 8 int n, m; 9 10 void sub(char* ca, char* cb, char* cc) {11   int a[maxn], b[maxn];12   memset(a, 0, sizeof(a));13   memset(b, 0, sizeof(b));14   int la = strlen(ca);15   int lb = strlen(cb);16   for(int i = 0; i < la; i++) a[i] = ca[la-i-1] - 0;17   for(int i = 0; i < lb; i++) b[i] = cb[lb-i-1] - 0;18   for(int i = 0; i < la; i++) {19     if(a[i] >= b[i]) a[i] -= b[i];20     else {21       a[i] = a[i] - b[i] + 10;22       a[i+1]--;23     }24   }25   int p = maxn;26   while(p--) if(a[p] != 0) break;27   for(int i = p; i >= 0; i--) cc[p-i] = a[i] + 0;28 }29 30 int main() {31   //freopen("in", "r", stdin);32   int T, _ = 1;33   scanf("%d", &T);34   while(T--) {35     scanf("%s", s);36     ret.clear();37     while(1) {38       n = strlen(s);39       if(strcmp("10", s) == 0) {40         ret.push_back("9");41         ret.push_back("1");42         break;43       }44       if(n == 1) {45         ret.push_back(s);46         break;47       }48       bool ex = 0;49       for(int i = n/2; i >= 0; i--) {50         if(s[i] != s[n-i-1]) {51           ex = 1;52           break;53         }54       }55       if(!ex) {56         ret.push_back(s);57         break;58       }59       memset(t, 0, sizeof(t));60       memset(::r, 0, sizeof(r));61       if(n == 2) {62         char tmp = min(s[0], s[1]);63         if(tmp != 0) t[0] = t[1] = tmp;64         else t[0] = t[1] = max(s[0], s[1]) - 1;65       }66       else {67         int l, r;68         if(n & 1) {69           for(int i = 0; i <= n/2; i++) t[i] = s[i];70           sub(t, "1", ::r); m = strlen(::r);71           memset(t, 0, sizeof(t));72           for(int i = 0; i < m; i++) t[i] = ::r[i];73           l = m - 2; r = m;74 //        if(m * 2 != n) l++;75           while(l >= 0) t[r++] = t[l--];76         }77         else {78           for(int i = 0; i < n/2; i++) t[i] = s[i];79           sub(t, "1", ::r); m = strlen(::r);80           memset(t, 0, sizeof(t));81           for(int i = 0; i < m; i++) t[i] = ::r[i];82           l = m - 1; r = m;83 //           if(m * 2 != n) l--;84           while(l >= 0) t[r++] = t[l--];85         }86       }87       ret.push_back(t);88       memset(r, 0, sizeof(r));89       sub(s, t, r);90       memcpy(s, r, sizeof(r));91     }92     printf("Case #%d:\n", _++);93     printf("%d\n", ret.size());94     for(int i = 0; i < ret.size(); i++) {95       printf("%s\n", ret[i].c_str());96     }97   }98   return 0;99 }
1010

 

[2016CCPC]长春现场赛重现