Codechef Bytecode 1-10

来源:互联网 发布:陕西网络干部学院 编辑:程序博客网 时间:2024/05/17 04:49

这个比赛好像不是很有名气,参加的人不多,前五题感觉比较平,题目有简单的也有中等的,但应该说不难,反正我是AK了。第3,4题还是很好的。

链接:http://www.codechef.com/BTCD2013/

1:

#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<cstdlib>#include<queue>#include<algorithm>#include<stack>#include<deque>#include<list>#include<set>#include<vector>#include<iomanip>#include<cctype>#include<string>#include<memory>#include<map>#include<sstream>#define mem(a) memset(a, 0, sizeof(a))#define For(i, n) for(int i = 0; i < (n); ++i)#define sl(a) strlen(a)typedef long long LL;typedef double dou;const int Mod = 1000000007;const double eps = 1e-8;const LL inf = 1e18;const int inf1 = 1e9;const int N = 100005;using namespace std; int a[N], l[N], r[N], dp[N][20]; int main(){LL n, m, t, i, j, k; cin >> t;while (t--){cin >> n >> m;cout << n * m - n - m << endl;}return 0;}
是一个数论结论,(a, b) = 1, a, b > 0 时ax + by (x, y >= 0) 不能表示的最大的整数是a * b - a - b.

证明: a 或 b 是1的情况是显然的,下设a > 1, b > 1.

首先a * b - a - b不能被表示。反证,设a * b - a - b = a * m + b * n 则 a * b = (m + 1)*a + (n + 1) * b.右边系数全部大于1。注意到左边是a的倍数,所以a |(n + 1)*b, 因为(a, b) = 1, 所以a | (n + 1), 所以(n + 1) * b > a * b, 矛盾。
再证a * b - a - b + i (i > 0) 能被表示。因为a,b互质,最大公约数就是1,根据辗转相减的方法知m*a+n*b=1,不妨假设m>0,n<0,于是a*b-a-b+i=a*b-a-b+i*(m*a+n*b)。因为m>1(m=0意味着n*b=1不可能的),所以a*b-a-b+i*(m*a+*b)=(i*m-1)a+(a+i*n-1)*b,i*m-1>0,现在只要证明a+i*n-1>=0,因为i*m*a+i*n*b=i,如果,|i*n|>j*a其中j>0,那么i*m*a=i+|i*n|*b>j*a*b,所以i*m>j*b,所以i*m*a+i*n*b=(i*m-j*b)a-(|i*n|-j*a)*b=i,说明|i*n|>j*a时,我们就能调整i*m,i*n使得|i*n|<a,因此|i*n|<=a-1, 所以a+i*n-1>=0于是得证。

2:

#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<cstdlib>#include<queue>#include<algorithm>#include<stack>#include<deque>#include<list>#include<set>#include<vector>#include<iomanip>#include<cctype>#include<string>#include<memory>#include<map>#include<sstream>#define mem(a) memset(a, 0, sizeof(a))#define For(i, n) for(int i = 0; i < (n); ++i)#define sl(a) strlen(a)typedef long long LL;typedef double dou;const int Mod = 1000000007;const double eps = 1e-8;const LL inf = 1e18;const int inf1 = 1e9;const int N = 100005;using namespace std; struct po{list<int>s;}p[20005]; int f[20005], vis[20005]; void dfs(int e, int s){vis[e] = 1;f[e] = s;list<int> :: iterator it = p[e].s.begin();while (it != p[e].s.end()){if (vis[*it] == 0)dfs(*it, e);it++;}} int main(){LL n, m, t, i, j, k, x, y; cin >> t;while (t--){cin >> n >> x >> y;for (i = 1; i <= n; ++i){if (i != x){cin >> m;p[i].s.push_back(m);p[m].s.push_back(i);}}dfs(y, y);for (i = 1; i <= n; ++i){if (i != y)cout << f[i] << ' ';}cout << endl;for (i = 1; i <= n; ++i) p[i].s.clear();mem(vis);}return 0;}

比较水的DFS.不多说。

5:

#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<cstdlib>#include<queue>#include<algorithm>#include<stack>#include<deque>#include<list>#include<set>#include<vector>#include<iomanip>#include<cctype>#include<string>#include<memory>#include<map>#include<sstream>#define mem(a) memset(a, 0, sizeof(a))#define For(i, n) for(int i = 0; i < (n); ++i)#define sl(a) strlen(a)typedef long long LL;typedef double dou;const int Mod = 1000000007;const double eps = 1e-8;const LL inf = 1e18;const int inf1 = 1e9;const int N = 100005;using namespace std; int num[200], vis[40], f[200], vv[200]; int main(){LL n, m, t, i, j, k, len, cnt, re;char s[100]; cin >> t;while (t--){mem(num), mem(s), mem(vis), mem(f), mem(vv);cin >> s;len = sl(s);cnt = re = 0;for (i = 0; i < len; ++i) num[s[i]]++;for (i = 0; i < 200; ++i) if (num[i]) cnt++;if (cnt == 1){cout << (1 << len) - 1 << endl;}else{f[s[0]] = 1, vis[1] = re = 1, vv[s[0]] = 1;for (i = 1; i < len; ++i) {if (vv[s[i]]) re = re * cnt + f[s[i]];else{for (j = 0; j < 40 && vis[j]; ++j);vis[j] = 1, f[s[i]] = j, vv[s[i]] = 1;re = re * cnt + j;}}cout << re << endl;}}return 0;}

(题意就是任给一串字符,你可以认为它是任何进制的数,但求它在十进制下的最小可能值)注意下进制数不能是1就可以了(wa了两次),首位也不能为0。

3和4是两道我觉得比较好的题。

思路都是DP, 其实3只能算递推,并没有涉及到动态保存能带来的好处,其实就是先算好了答案,放在数组里而已。代码中后有着重的地方是关键。

#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<cstdlib>#include<queue>#include<algorithm>#include<stack>#include<deque>#include<set>#include<vector>#include<iomanip>#include<cctype>#include<string>#include<memory>#include<map>#include<sstream>#pragma warning (disable : 4996)#define mem(a) memset(a, 0, sizeof(a))#define For(i, n) for(int i = 0; i < (n); ++i)#define sl(a) strlen(a)typedef long long LL;typedef double dou;const int Mod = 1000000007;const double eps = 1e-8;const LL inf = 1e18;const int inf1 = 1e9;const int N = 100005;using namespace std;#define M 12LL dp[10][10][600];LL ans[10][600]; int main (){LL i, j, k, n, m, t, re; for (i = 1; i < 10; ++i) //最大可取数字为i,首位为j,长度为k dp[i][i][i + 1] = dp[i][0][i + 1] = 1;for (i = 1; i < 10; ++i)for (k = i + 2; k < 510; ++k) //*****//for (j = 0; j <= i; ++j){if (j == 0) dp[i][0][k] = (dp[i][1][k - 1] + dp[i - 1][0][k - 1]) % Mod; //******************//else if (j == i) dp[i][i][k] = (dp[i][i - 1][k - 1] + dp[i - 1][i - 1][k - 1]) % Mod;else dp[i][j][k] = (dp[i][j - 1][k - 1] + dp[i][j + 1][k - 1]) % Mod;   //******************//}for (i = 1; i < 10; ++i)for (k = i + 1; k < 510; ++k) //****//for (j = 1, ans[i][k] = ans[i][k - 1]; j <= i; ++j) //*****//ans[i][k] = (ans[i][k] + dp[i][j][k]) % Mod;cin >> t;while (t--){scanf("%lld%lld", &n, &m);if (n > m) printf("0\n");else printf("%lld\n", ans[n - 1][m]);}return 0;} 

4:

首先考虑一个两段开的区间(i , j), dp[i][j]表示从a[i]到a[j]的所有可能方案的代价最小值。设两个哨兵0, n+1.枚举i, j 之间所有第一步可取的方案,划归为子问题。取最小即可。最后写出来的代码倒是很简洁。(一开始贪心,猜的策略。。。wa了好多次)。复杂度是Z*Z*Z,10^6可以接受。

#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<cstdlib>#include<queue>#include<algorithm>#include<stack>#include<deque>#include<list>#include<set>#include<vector>#include<iomanip>#include<cctype>#include<string>#include<memory>#include<map>#include<sstream>#define mem(a) memset(a, 0, sizeof(a))#define For(i, n) for(int i = 0; i < (n); ++i)#define sl(a) strlen(a)typedef long long LL;typedef double dou;const int Mod = 1000000007;const double eps = 1e-8;const LL inf = 1e18;const int inf1 = 1e9;const int N = 100005;using namespace std; int a[105], dp[105][105]; int main(){int  n, m, re, t, i, j, k; cin >> t;while (t--){cin >> m >> n;mem(dp);for (i = 1; i <= n; ++i) cin >> a[i];a[n + 1] = m + 1;for (i = 2; i <= n + 1; ++i) for (j = 0; j + i <= n + 1; ++j){for (k = j + 1; k < i + j; ++k){if (k == j + 1) dp[j][i + j] = (a[i + j] - a[j] - 2 + dp[j][k] + dp[k][i + j]);else dp[j][i + j] =  dp[j][i + j] > (a[i + j] - a[j] - 2 + dp[j][k] + dp[k][i + j]) ?  (a[i + j] - a[j] - 2 + dp[j][k] + dp[k][i + j]) : dp[j][i + j];}}cout << dp[0][n + 1] << endl;}return 0;}

希望22号,另五道不要忽然变得特别难,能拿个好的名次.^_^

接着写。。。。无力吐槽数据。。。

6:

#include<cstdio>#include<cstdlib>#include<cmath>#include<set>#include<iostream>#define LL long longusing namespace std;  set<int> p; bool witness(LL a,LL n){    LL t,d,x;    d=1;    int i=ceil(log(n-1.0)/log(2.0)) - 1;    for(;i>=0;i--)    {        x=d;  d=(d*d)%n;        if(d==1 && x!=1 && x!=n-1) return true;        if( ((n-1) & (1<<i)) > 0)            d=(d*a)%n;    }    return d==1 ? false : true;} bool miller_rabin(LL n){    int s[]={2,7,61};    if(n==2)    return true;    if(n==1 || ((n&1)==0))    return false;    for(int i=0;i<3;i++)        if(witness(s[i], n))    return false;    return true;} int main(){    int n,cnt, x, y, i, j, t, en;cin >> t;                 while(t--)    {cin >> x >> y;cnt=0;for (i = 1; i * i < y / 2; ++i){en = (int) sqrt(y - i * i + 0.5);for (j = i + 1; j <= en; j += 2)if (i * i + j * j >= x)if (miller_rabin(i * i + j * j)) {if (!p.count(i * i + j * j)){cnt++;p.insert(i * i + j * j);}}}if (x <= 2 && y >= 2) cnt++;   cout << cnt << endl;   p.clear();    }    return 0;} 

7:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define mem(a) memset(a, 0, sizeof(a))#define N 100005#define M 1000005#define LL long long#pragma warning (disable : 4996)using namespace std; struct po{int x, l, cnt, id;bool operator < (const po &t) const{return x < t.x;}}p[N]; bool cmp(po a, po b){return a.id < b.id;} int main(){int n, i, j, k, t, q, min, sum;cin >> t;while (t--){mem(p);cin >> n;for (i = 0; i < n; ++i) scanf("%d%d", &(p[i].x), &(p[i].l)), p[i].cnt = 0, p[i].id = i;sort(p, p + n);for (i = n - 1; i >= 0; --i) {p[i].cnt = 1, p[i].l += p[i].x - 1;for (j = i + 1; p[j].x <= p[i].l && j < n; ++j) p[i].cnt++, p[i].l = max(p[i].l, p[j].l);}sort(p, p + n, cmp);for (i = 0; i < n; ++i) printf("%d ", p[i].cnt);cout << endl;}return 0;}
8:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define mem(a) memset(a, 0, sizeof(a))#define N 1000005#define LL long long#pragma warning (disable : 4996)using namespace std; int ql, qr, a[N], b[N], num[N], kill; struct no{int cnt, l, r;}n[4*N]; void bld(int x, int l, int r){int m = (l + r) >> 1;n[x].cnt = 0;n[x].l = l;n[x].r = r; if (r == l) return ;else bld(2* x, l, m), bld(2 * x + 1, m + 1, r); } void maint(int x, int l, int r){int ls = x * 2, rs = 2 * x + 1, m = (l + r) >> 1;if (l < r){n[ls].cnt += n[x].cnt, n[rs].cnt += n[x].cnt;maint(ls, l, m), maint(rs, m + 1, r);}else num[kill++] = n[x].cnt;} void upd(int x, int l, int r){int m = (l + r) >> 1, ls = 2 * x, rs = 2 * x + 1;if (l == r) n[x].cnt++;else{if (ql <= l&& qr >= r)  n[x].cnt++;else {if (ql <= m) upd(ls, l, m);if(qr > m) upd(rs, m + 1, r);}}}  int main(){int nn, i, j, k, t, q;LL re;while (cin >> t){mem(n), mem(num), kill = 0;cin >> nn >> q;for (i = 0; i < nn; ++i) cin >> a[i];sort(a, a + nn);bld(1, 1, nn);for (i = 0; i < q; ++i) {cin >> ql >> qr;upd(1, 1, nn);}maint(1, 1, nn);sort(num, num + nn);for (i = 0, re = 0; i < nn; ++i)re += a[i] * num[i];cout << re << endl;}return 0;}
9:

#include<iostream>#include<cstring>#include<set>#include<cstdio>#pragma warning (disable : 4996)using namespace std;#define N 100005 struct po{int x, y;bool operator < (const po &t) const{if (x != t.x) return x < t.x;else return y < t.y;}}p[N]; set<po> a; int main(){int n, i, j, k, x, y;char s[10] = {0};po tem;set<po>:: iterator iter;cin >> n;while (n--){scanf("%s%d%d", s, &(tem.x), &(tem.y));if (s[0] == 'a'){if (!a.count(tem)) a.insert(tem);}else if (s[0] == 'e') a.erase(tem);else {if (a.count(tem)){iter = a.find(tem);iter++;if (iter == a.end()) printf("-1\n");else printf("%d %d\n", (*iter).x, (*iter).y);}else{a.insert(tem);iter = a.find(tem);iter++;if (iter == a.end()) printf("-1\n");else printf("%d %d\n", (*iter).x, (*iter).y);a.erase(tem);}}}return 0;}

10:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define mem(a) memset(a, 0, sizeof(a))#define N 100005#define M 1000005#define LL long long#pragma warning (disable : 4996)using namespace std;int a[N]; int main(){int n, i, j, k, t, q, min, sum;LL re;cin >> t;while (t--){cin >> n;for (i = 0, min = M, re = sum = 0; i < n; ++i) scanf("%d", a + i), min = min > a[i] ? a[i] : min, re ^= a[i], sum += a[i];if (re == 0)cout << sum - min << endl;else cout << "NO\n";}return 0;}

水到不能再水。。。。Orz