开始套题训练,第一套ASC题目,记住不放过每一题,多独立思考。
Problem A ZOJ 2313 Chinese Girls‘ Amusement 循环节
题意:给定n,为圆环长度,求k <= n/2,从1出发,每次顺时针方向走k步,即1->k+1->2*k+1,直到遇到一个已经走过的点结束,要求最终把所有点访问一遍,最后回到1,使得k尽量大。
代码:
Problem B ZOJ 2314 Reactor Cooling 无源汇上下界网络流
题意:经典题,有上下界无源无汇的可行流,对于每条边u->v,上界流量C(u,v),下界流量B(u, v),可以这样构图,建立附加源点S,T对于每条边u->v,在流量图中连一条容量为C(u, v)-B(u, v)的边,同时S->v连容量B(u, v) 的边,u->T连B(u, v) 的边,跑一遍网络流,当从S出发的边满流时,有可行流,原图中每条边流量为相应B(u, v)+最大流图中流量g(u, v).
代码:
1 #include <bits/stdc++.h> 2 #define pb push_back 3 #define mp make_pair 4 5 #define lson l, m, rt<<1 6 #define rson m+1, r, rt<<1|1 7 #define sz(x) ((int)((x).size())) 8 #define pb push_back 9 #define in freopen("solve_in.txt", "r", stdin); 10 #define bug(x) printf("Line : %u >>>>>>\n", (x)); 11 #define inf 0x0f0f0f0f 12 using namespace std; 13 typedef long long LL; 14 typedef map<int, int> MPS; 15 typedef pair<int, int> PII; 16 const int maxn = 222; 17 struct Node { 18 int c, l, id; 19 Node() {} 20 Node(int c, int l, int id):c(c), l(l), id(id) {} 21 }; 22 vector<Node> cap; 23 24 25 struct Edge { 26 int u, v, c; 27 Edge(int u, int v, int c):u(u), v(v), c(c) {} 28 }; 29 struct Max_flow { 30 int n, m; 31 int src, sink; 32 vector<Edge> edges; 33 vector<int> G[maxn]; 34 int Now[maxn], Dfn[maxn], cur[maxn]; 35 void init(int n) { 36 this->n = n; 37 for(int i = 0; i < n; i++) G[i].clear(); 38 edges.clear(); 39 } 40 void add(int u, int v, int c) { 41 edges.pb(Edge(u, v, c)); 42 edges.pb(Edge(v, u, 0)); 43 m = edges.size(); 44 G[u].pb(m-2); 45 G[v].pb(m-1); 46 } 47 int ISAP(int s, int flow) { 48 if(s == sink) 49 return flow; 50 int i, tab = n, vary, now = 0; 51 int p = cur[s]; 52 do { 53 Edge &e = edges[G[s][cur[s]]]; 54 if(e.c > 0) { 55 if(Dfn[s] == Dfn[e.v]+1) 56 vary = ISAP(e.v, min(flow-now, e.c)), 57 now += vary, e.c -= vary, edges[G[s][cur[s]]^1].c += vary; 58 if(Dfn[src] == n) 59 return now; 60 if(e.c > 0) tab = min(tab, Dfn[e.v]); 61 if(flow == now) 62 break; 63 } 64 cur[s]++; 65 if(cur[s] == (int)G[s].size()) cur[s] = 0; 66 } while(p != cur[s]); 67 if(now == 0) { 68 if(--Now[Dfn[s]] == 0) 69 Dfn[src] = n; 70 Now[Dfn[s] = tab+1]++; 71 } 72 return now; 73 } 74 int max_flow(int src, int sink) { 75 this->src = src; 76 this->sink = sink; 77 int flow = 0; 78 memset(Dfn, 0, sizeof Dfn); 79 memset(Now, 0, sizeof Dfn); 80 memset(cur, 0, sizeof cur); 81 Now[0] = n; 82 for(; Dfn[src] < n;) 83 flow += ISAP(src, inf); 84 return flow; 85 } 86 } mc; 87 vector<int> mx; 88 89 int main() { 90 91 int T; 92 for(int t = scanf("%d", &T); t <= T; t++) { 93 int n, m; 94 cap.clear(); 95 mx.clear(); 96 97 scanf("%d%d", &n, &m); 98 mc.init(n+2); 99 int src = n, sink = n+1; 100 101 for(int i = 1; i <= m; i++) { 102 int u, v, c, l; 103 scanf("%d%d%d%d", &u, &v, &l, &c); 104 u--, v--; 105 mc.add(u, v, c-l); 106 int tmp = mc.edges.size()-2; 107 cap.pb(Node(c, l, tmp)); 108 mc.add(src, v, l); 109 tmp = mc.edges.size()-2; 110 mx.pb(tmp); 111 mc.add(u, sink, l); 112 } 113 int flow = mc.max_flow(src, sink); 114 //// cout << flow << endl; 115 int ok = 1; 116 for(int i = 0; i < (int)mx.size(); i++) { 117 int id = mx[i]; 118 if(mc.edges[id].c) { 119 ok = 0; 120 break; 121 } 122 } 123 124 if(t != 1) puts(""); 125 if(ok) { 126 puts("YES"); 127 for(int i = 0; i < (int)cap.size(); i++) { 128 Node x = cap[i]; 129 int id = x.id; 130 printf("%d\n", x.c-mc.edges[id].c); 131 } 132 } else puts("NO"); 133 } 134 return 0; 135 }
关于上下界网络流补充资料:http://blog.sina.com.cn/s/blog_76f6777d0101bara.html
Problem C ZOJ 2315 New Year Bonus Grant 树形dp或贪心
题意:以1为根的树中,每个结点可以从父节点获得一个奖励,或者自己给其中一个子节点的奖励,或者既不获得也不给出奖励。求所有结点获得的最大奖励数目
分析:我是用树形dp做的,dp[u][i],i为1表示从父亲结点获得奖励时该子树最大奖励和,dp[u][0]为不从父节点获得奖励时该子树的最大奖励和。
代码:
1 #include <bits/stdc++.h> 2 #define pb push_back 3 #define mp make_pair 4 5 #define lson l, m, rt<<1 6 #define rson m+1, r, rt<<1|1 7 #define sz(x) ((int)((x).size())) 8 #define pb push_back 9 #define in freopen("solve_in.txt", "r", stdin); 10 #define bug(x) printf("Line : %u >>>>>>\n", (x)); 11 #define inf 0x0f0f0f0f 12 using namespace std; 13 typedef long long LL; 14 typedef map<int, int> MPS; 15 typedef pair<int, int> PII; 16 const int maxn = (int)5e5 + 100; 17 vector<int> g[maxn]; 18 int dp[maxn][2], pa[maxn]; 19 void dfs(int u, int fa) { 20 int sum = 0; 21 dp[u][0] = dp[u][1] = -1; 22 pa[u] = -1; 23 for(int i = 0; i < sz(g[u]); i++) { 24 int v = g[u][i]; 25 if(v == fa) continue; 26 dfs(v, u); 27 sum += dp[v][0]; 28 } 29 dp[u][1] = 1 + sum; 30 dp[u][0] = sum; 31 for(int i = 0; i < sz(g[u]); i++) { 32 int v = g[u][i]; 33 if(v == fa) continue; 34 if(sum-dp[v][0]+dp[v][1] > dp[u][0]) 35 dp[u][0] = sum-dp[v][0]+dp[v][1], pa[u] = v; 36 } 37 } 38 vector<int> ans; 39 void printAns(int u, int st, int fa) { 40 if(st) ans.pb(u); 41 for(int i = 0; i < sz(g[u]); i++) { 42 int v = g[u][i]; 43 if(v == fa) continue; 44 printAns(v, v == pa[u] && !st, u); 45 } 46 } 47 int main() { 48 49 int T; 50 for(int t = scanf("%d", &T); t <= T; t++) { 51 if(t != 1) puts(""); 52 int n; 53 ans.clear(); 54 scanf("%d", &n); 55 for(int i = 1; i <= n; i++) g[i].clear(); 56 for(int i = 1; i < n; i++) { 57 int u; 58 scanf("%d", &u); 59 g[u].pb(i+1); 60 } 61 dfs(1, 0); 62 printf("%d\n", 1000*dp[1][0]); 63 printAns(1, 0, 0); 64 sort(ans.begin(), ans.end()); 65 for(int i = 0; i < (int)ans.size(); i++) { 66 printf("%d%c", ans[i], i == (int)ans.size()-1 ? ‘\n‘ : ‘ ‘); 67 } 68 } 69 return 0; 70 }
Problem D ZOJ 2316 Matrix Multiplication 顶点度数
题意:给定一个图,n个顶点,m条边,最终就是要你求每个点度数平方之和。
分析:注意防止溢出。
1 #include <bits/stdc++.h> 2 #define pb push_back 3 #define mp make_pair 4 5 #define lson l, m, rt<<1 6 #define rson m+1, r, rt<<1|1 7 #define sz(x) ((int)((x).size())) 8 #define pb push_back 9 #define in freopen("solve_in.txt", "r", stdin); 10 #define bug(x) printf("Line : %u >>>>>>\n", (x)); 11 #define inf 0x0f0f0f0f 12 using namespace std; 13 typedef long long LL; 14 typedef map<int, int> MPS; 15 MPS mps; 16 17 const int maxn = 10000 + 100; 18 int num[maxn]; 19 int cnt; 20 21 int idx(int x){ 22 if(mps.count(x) == false) 23 mps[x] = ++cnt; 24 return mps[x]; 25 } 26 int main(){ 27 28 int T; 29 for(int t = scanf("%d", &T); t <= T; t++){ 30 memset(num, 0, sizeof num); 31 int n, m; 32 mps.clear(); 33 cnt = 0; 34 scanf("%d%d", &n, &m); 35 for(int i = 1; i <= m; i++){ 36 int u, v; 37 scanf("%d%d", &u, &v); 38 u = idx(u); 39 v = idx(v); 40 num[u]++, num[v]++; 41 } 42 LL ans = 0; 43 for(int i = 1; i <= n;i++){ 44 ans += (LL)num[i]*num[i]; 45 } 46 if(t != 1) puts(""); 47 printf("%lld\n", ans); 48 } 49 return 0; 50 }
Problem E ZOJ 2317 Nice Patterns Strike Back 矩阵快速幂,组合数
题意:一个n*m的方格,每个格子有两种颜色,现在给整个方格涂色,要求一个2*2的正方形内颜色不能相同,问有多少种颜色,m<=5, n <= 10^100,最终结果模p,p <= 10000。
分析:由于能否构成同样颜色正方形取决于当前列连续2格以及前一列的对应两列是否颜色一样,所以对每列的状态,st看能从哪些状态st‘转移过来。这样可以建立一个转移图
边u->v表示前一列状态为u下列可为v。dp[i+1][u] = sum{dp[i][v]},可以得到一个矩阵,g[v][u]表示v转移到u,那么答案就是g^n然后取结果矩阵sum{g[i][0]}之和。
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <map> 4 #include <cstring> 5 #include <vector> 6 #include <cmath> 7 #include <cassert> 8 #include <algorithm> 9 #define pb push_back 10 #define mp make_pair 11 #define esp 1e-8 12 #define lson l, m, rt<<1 13 #define rson m+1, r, rt<<1|1 14 #define sz(x) ((int)((x).size())) 15 #define pb push_back 16 #define in freopen("solve_in.txt", "r", stdin); 17 #define bug(x) printf("Line : %u >>>>>>\n", (x)); 18 #define inf 0x0f0f0f0f 19 using namespace std; 20 typedef long long LL; 21 typedef map<int, int> MPS; 22 typedef pair<int, int> PII; 23 24 const int maxn = 111; 25 const int maxm = 44; 26 const int B = 10000; 27 int m, p; 28 29 struct BigInt { 30 int dig[maxn], len; 31 BigInt(int num = 0):len(!!num) { 32 memset(dig, 0, sizeof dig); 33 dig[0] = num; 34 } 35 int operator [](int x)const { 36 return dig[x]; 37 } 38 int& operator [](int x) { 39 return dig[x]; 40 } 41 BigInt normalize() { 42 while(len && dig[len-1] == 0) len--; 43 return *this; 44 } 45 void output() { 46 if(len == 0) { 47 puts("0"); 48 return; 49 } 50 printf("%d", dig[len-1]); 51 for(int i = len-2; i >= 0; i--) 52 printf("%04d", dig[i]); 53 puts(""); 54 } 55 }; 56 BigInt operator / (BigInt a, int b) { 57 BigInt c; 58 c.len = a.len; 59 for(int i = a.len-1, delta = 0; i >= 0; i--) { 60 delta = delta*B+a[i]; 61 c[i] = delta/b; 62 delta %= b; 63 } 64 return c.normalize(); 65 } 66 bool operator == (const BigInt &a, const BigInt &b) { 67 if(a.len != b.len) return false; 68 for(int i = a.len-1; i >= 0; i--) if(a[i] != b[i]) return false; 69 return true; 70 } 71 struct Matrix { 72 int a[maxm][maxm]; 73 Matrix() { 74 memset(a, 0, sizeof a); 75 } 76 }; 77 Matrix operator * (const Matrix &a, const Matrix &b) { 78 Matrix c; 79 for(int i = 0; i < (1<<m)+1; i++) for(int j = 0; j < (1<<m)+1; j++) { 80 for(int k = 0; k < (1<<m)+1; k++) 81 c.a[i][j] = (c.a[i][j] + (LL)a.a[i][k]*b.a[k][j]%p)%p; 82 } 83 return c; 84 } 85 char s[111]; 86 int b[] = {1, 10, 100, 1000}; 87 88 bool check(int x, int y) { 89 for(int i = 0; i < m-1; i++) { 90 if((((x>>i)&1) && ((x>>(i+1))&1) 91 && ((y>>i)&1) && ((y>>(i+1))&1)) || (!((x>>i)&1) && !((x>>(i+1))&1) 92 && !((y>>i)&1) && !((y>>(i+1))&1))) 93 return false; 94 } 95 return true; 96 } 97 int main() { 98 99 100 int T; 101 for(int t = scanf("%d", &T); t <= T; t++) { 102 if(t != 1) puts(""); 103 scanf("%s%d%d", s, &m, &p); 104 int len = strlen(s); 105 BigInt c; 106 for(int i = len-1; i >= 0; i--) { 107 c[(len-1-i)/4] += b[(len-1-i)%4]*(s[i]-‘0‘); 108 c.len = max(c.len, (len-1-i)/4+1); 109 } 110 Matrix res, g; 111 for(int i = 0; i < maxm; i++) for(int j = 0; j < maxm; j++) res.a[i][j] = i == j; 112 for(int i = 0; i < (1<<m); i++) { 113 g.a[i+1][0] = 1; 114 for(int j = 0; j < (1<<m); j++) if(check(i, j)) { 115 g.a[j+1][i+1] = 1; 116 } 117 } 118 while(c.len) { 119 if(c[0]&1) res = res*g; 120 g = g*g; 121 c = c/2; 122 } 123 int ans = 0; 124 for(int i = 1; i <= (1<<m); i++) 125 ans = (ans + res.a[i][0])%p ; 126 printf("%d\n", ans); 127 } 128 return 0; 129 }
一个升级版的题目,不过要用到中国剩余定理:
Problem F ZOJ 2318 Get Out! 有向角度判别法,spfa判负环
题意:给定一些圆,然后自己也是一个圆能否从中突出重围。
分析:将自己的半径加到其他圆上面,并平移坐标系以自己所在坐标为原点,将相交的圆心连一条边,然后问题变成了,看是否有一个多边形包围原点。利用有向视角判别法,每条边两个顶点与原点构成的角度a作为权值,对应原来的边建图,两条有向边,权值对应为a和-a。这样就看原图是否有负环了。利用spfa判别就行。位于多边形外面时显然角度和位0。内部则为360或-360度
注意:本题分析显然不会位于多边形顶点或边界上面,否则可能会出错?spfa判别法注意精度。
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <map> 4 #include <cstring> 5 #include <vector> 6 #include <cmath> 7 #include <cassert> 8 #include <algorithm> 9 #include <queue> 10 #define pb push_back 11 #define mp make_pair 12 #define esp 1e-8 13 #define lson l, m, rt<<1 14 #define rson m+1, r, rt<<1|1 15 #define sz(x) ((int)((x).size())) 16 #define pf(x) ((x)*(x)) 17 #define pb push_back 18 #define in freopen("solve_in.txt", "r", stdin); 19 #define bug(x) printf("Line : %u >>>>>>\n", (x)); 20 #define inf 0x0f0f0f0f 21 using namespace std; 22 typedef long long LL; 23 typedef map<int, int> MPS; 24 typedef pair<int, int> PII; 25 26 const int maxn = 333; 27 double x[maxn], y[maxn], r[maxn], len[maxn]; 28 29 struct Edge { 30 int u, v; 31 double w; 32 Edge() {} 33 Edge(int u, int v, double w):u(u), v(v), w(w) {} 34 }; 35 vector<Edge> edges; 36 vector<int> g[maxn]; 37 int n, m; 38 39 void init() { 40 edges.clear(); 41 for(int i = 0; i < maxn; i++) g[i].clear(); 42 } 43 void add(int u, int v, double w) { 44 edges.pb(Edge(u, v, w)); 45 m = edges.size(); 46 g[u].pb(m-1); 47 } 48 inline bool check(double x1, double y1, double x2, double y2) { 49 return (x1*y2-y1*x2) >= 0; 50 } 51 int inq[maxn]; 52 double dist[maxn]; 53 int cnt[maxn]; 54 55 bool spfa() { 56 queue<int> q; 57 memset(inq, 0, sizeof inq); 58 for(int i = 1; i <= n; i++) { 59 inq[1] = 1; 60 cnt[i] = 0; 61 dist[i] = 0; 62 q.push(i); 63 } while(q.size()) { 64 int u = q.front(); 65 q.pop(); 66 inq[u] = 0; 67 for(int i = 0; i < sz(g[u]); i++) { 68 Edge e = edges[g[u][i]]; 69 int v = e.v; 70 double c = e.w; 71 if(dist[v] > dist[u] + c + esp) { 72 if(dist[v] = dist[u] + c, !inq[v]) { 73 q.push(v); 74 inq[v] = 1; 75 if(++cnt[v] > n + 10) { 76 return true; 77 } 78 } 79 } 80 } 81 } 82 return false; 83 } 84 int main() { 85 86 int T; 87 for(int t = scanf("%d", &T); t <= T; t++) { 88 if(t != 1) puts(""); 89 init(); 90 for(int i = scanf("%d", &n); i <= n+1; i++) { 91 scanf("%lf%lf%lf", x+i, y+i, r+i); 92 } 93 for(int i = 1; i <= n; i++) { 94 x[i] -= x[n+1]; 95 y[i] -= y[n+1]; 96 len[i] = sqrt(pf(x[i])+pf(y[i])); 97 r[i] += r[n+1]; 98 } 99 for(int i = 1; i <= n; i++) 100 for(int j = i+1; j <= n; j++) { 101 if(sqrt(pf(x[i]-x[j]) + pf(y[i]-y[j])) >= r[i]+r[j]) 102 continue; 103 double ang = acos((x[i]*x[j]+y[i]*y[j])/len[i]/len[j]); 104 bool ok = check(x[i], y[i], x[j], y[j]); 105 add(i, j, ok ? ang : -ang); 106 add(j, i, ok ? -ang : ang); 107 } 108 if(spfa()) 109 puts("NO"); 110 else puts("YES"); 111 } 112 return 0; 113 }
Problem G ZOJ 2319 Beautiful People LIS
题意:有n个元素,每个元素是一个对数ai,bi,然后从中选出一些元素,能够排成一列ai < ai+1, 且bi < bi+1,问最长选出多少个元素。
分析:看上去像是LIS,其实也是利用这个,由于ai肯定是单调递增的,所以先按ai小到大排序,bi从大到小排序,然后只要按照bi选出LIS就行了。利用O(nlogn)的经典做法可做。
代码:
1 #include <bits/stdc++.h> 2 #define pb push_back 3 #define mp make_pair 4 5 #define lson l, m, rt<<1 6 #define rson m+1, r, rt<<1|1 7 #define sz(x) ((int)((x).size())) 8 #define pb push_back 9 #define in freopen("solve_in.txt", "r", stdin); 10 #define bug(x) printf("Line : %u >>>>>>\n", (x)); 11 #define inf 0x0f0f0f0f 12 using namespace std; 13 typedef long long LL; 14 typedef map<int, int> MPS; 15 typedef pair<int, int> PII; 16 17 const int maxn = (int)1e5 + 100; 18 int f[maxn], dp[maxn]; 19 MPS mps; 20 21 struct Node { 22 int s, b, id; 23 Node() {} 24 Node(int s, int b, int id):s(s), b(b), id(id) {} 25 bool operator < (const Node &rhs)const { 26 if(s != rhs.s) return s < rhs.s; 27 return b > rhs.b; 28 } 29 } a[maxn]; 30 int g[maxn]; 31 int cnt; 32 int idx(int x) { 33 if(mps.count(x) == false) 34 mps[x] = ++cnt; 35 return mps[x]; 36 } 37 38 int main() { 39 40 int T; 41 for(int t = scanf("%d", &T); t <= T; t++) { 42 int n; 43 cnt = 0; 44 if(t != 1) puts(""); 45 scanf("%d", &n); 46 mps.clear(); 47 for(int i = 1; i <= n; i++) { 48 scanf("%d%d", &a[i].s, &a[i].b); 49 //// a[i].s = idx(a[i].s); 50 //// a[i].b = idx(a[i].b); 51 a[i].id = i; 52 } 53 memset(dp, 0, sizeof dp); 54 sort(a+1, a+n+1); 55 memset(f, 0x7f, sizeof f); 56 int ans = 0, u; 57 for(int i = 1; i <= n; i++) { 58 int k = lower_bound(f+1, f+n+1, a[i].b)-f-1; 59 if(ans < k+1) 60 ans = k+1, u = i; 61 f[k+1] = a[i].b; 62 g[k+1] = i; 63 dp[i] = g[k]; 64 } 65 cout << ans << endl; 66 int ok = 0; 67 while(u) { 68 if(ok) cout << ‘ ‘; 69 else ok ^= 1; 70 cout << a[u].id; 71 u = dp[u]; 72 } 73 puts(""); 74 } 75 return 0; 76 }
Problem H ZOJ 2320 Cracking‘ RSA 高斯消元
题意:给定m个数,其素因子来自前t个素数,m <= 100,t <= 100。求m个数构成的集合,从中选出一些数构成子集,所有元素之积为完全平方数。有多少种方案。
分析:考虑每个数有选和不选两种状态,用未知量xi表示,由于最终选出来的数的积为完全平方数,所以其乘积中,对于前t个素数的数目必须为偶数个,即模2为0。
所以容易建立t个方程,对每个数分解质因数,质因数个数模2为0,这是一个线性方程组,方程一定有解,所以设自由元个数n,答案2^n-1,这里要用到大数。
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <map> 4 5 #include <cstring> 6 #include <vector> 7 #include <cmath> 8 #include <cassert> 9 #include <algorithm> 10 #define pb push_back 11 #define mp make_pair 12 #define esp 1e-8 13 #define lson l, m, rt<<1 14 #define rson m+1, r, rt<<1|1 15 #define sz(x) ((int)((x).size())) 16 #define pb push_back 17 #define in freopen("solve_in.txt", "r", stdin); 18 #define bug(x) printf("Line : %u >>>>>>\n", (x)); 19 #define inf 0x0f0f0f0f 20 using namespace std; 21 typedef long long LL; 22 typedef map<int, int> MPS; 23 typedef pair<int, int> PII; 24 25 const int maxn = 110; 26 const int B = 10000; 27 28 int num[maxn][maxn], prime[maxn], vis[2222]; 29 int a[maxn][maxn]; 30 void seivePrime() { 31 int tot = 0; 32 for(int i = 2; i < 2000; i++) { 33 if(!vis[i]) prime[++tot] = i; 34 35 for(int j = 1; j <= tot; j++){ 36 if(prime[j]*i >= 2000) break; 37 vis[i*prime[j]] = 1; 38 if(i%prime[j] == 0) break; 39 } 40 if(tot >= 150) break; 41 } 42 } 43 int n, m; 44 void getFact(int b, LL x) { 45 for(int i = 1; i <= n; i++) { 46 if(x%prime[i] == 0) { 47 while(x%prime[i] == 0) { 48 num[b][i-1]++; 49 x /= prime[i]; 50 } 51 if(x == 1) 52 break; 53 } 54 } 55 } 56 int Gauss(int equ, int var) { 57 int k, r, col; 58 for(k = col = 0; k < equ && col < var; k++, col++) { 59 r = k; 60 for(int i = k+1; i < equ; i++) if(a[i][col]) { 61 r = i; 62 break; 63 } 64 if(r != k) for(int i = col; i <= var; i++) 65 swap(a[r][i], a[k][i]); 66 if(a[k][col] == 0) { 67 k--; 68 continue; 69 } 70 for(int i = k+1; i < equ; i++) if(a[i][col]) 71 for(int j = col; j <= var; j++) 72 a[i][j] ^= a[k][j]; 73 } 74 return var-k; 75 } 76 struct BigInt { 77 int dig[maxn], len; 78 BigInt(int num = 0):len(!!num) { 79 memset(dig, 0, sizeof dig); 80 dig[0] = num; 81 } 82 int operator [](int x)const { 83 return dig[x]; 84 } 85 int &operator [](int x) { 86 return dig[x]; 87 } 88 BigInt normalize() { 89 while(len > 1 && dig[len-1] == 0) len--; 90 return *this; 91 } 92 void output() { 93 printf("%d", dig[len-1]); 94 for(int i = len-2; i >= 0; i--) 95 printf("%04d", dig[i]); 96 puts(""); 97 } 98 }; 99 BigInt operator - (BigInt a, int b) { 100 BigInt c; 101 c.len = a.len; 102 for(int i = 0, delta = -b; i < a.len; i++) { 103 c[i] = delta+a[i]; 104 delta = 0; 105 if(c[i] < 0) { 106 delta = -1; 107 c[i] = c[i]+B; 108 } 109 } 110 return c.normalize(); 111 } 112 BigInt operator *(BigInt a, BigInt b) { 113 BigInt c; 114 c.len = a.len+b.len+1; 115 for(int i = 0; i < a.len; i++) 116 for(int j = 0, delta = 0; j <= b.len; j++) { 117 delta += (c[i+j]+a[i]*b[j]); 118 c[i+j] = delta%B; 119 delta /= B; 120 } 121 return c.normalize(); 122 } 123 void print(int x){ 124 int i , len = 1 , ans[100]; 125 memset(ans,0,sizeof(ans)); 126 ans[1] = 1; 127 while (x--){ 128 for (i=1;i<=len;++i) ans[i]*=2; 129 for (i=1;i<=len;++i) 130 ans[i+1] += ans[i]/10 , ans[i] %= 10; 131 if (ans[len+1]) ++len; 132 } 133 --ans[1]; 134 for (i=len;i>=1;--i) printf("%d",ans[i]); 135 puts(""); 136 } 137 int main() { 138 139 int T; 140 seivePrime(); 141 for(int t = scanf("%d", &T); t <= T; t++) { 142 if(t != 1) puts(""); 143 memset(num, 0, sizeof num); 144 memset(a, 0, sizeof a); 145 scanf("%d%d", &n, &m); 146 for(int i = 0; i < m; i++) { 147 int x; 148 scanf("%d", &x); 149 for(int ii = 1; ii <= n; ii++) { 150 if(x%prime[ii] == 0) { 151 while(x%prime[ii] == 0) { 152 a[ii-1][i] ^= 1; 153 x /= prime[ii]; 154 } 155 } 156 } 157 } 158 int vary = Gauss(n, m); 159 if(vary == 0) puts("0"); 160 else 161 print(vary); 162 } 163 return 0; 164 }
原文:http://www.cnblogs.com/rootial/p/4075129.html