[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 }
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 }
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 }
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 }
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 }
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 }