国庆打了场组队 效果还不错 季军 现在发下题解
A:
高精度模拟即可 与n互素的数不会离n/2太远 直接暴力
代码:
#include<stdio.h> #include<string> #include<string.h> #include<iostream> using namespace std; //compare比较函数:相等返回0,大于返回1,小于返回-1 int compare(string str1, string str2) { if (str1.length() > str2.length()) return 1; else if (str1.length() < str2.length()) return -1; else return str1.compare(str2); } //高精度加法 //只能是两个正数相加 string add(string str1, string str2) //高精度加法 { string str; int len1 = str1.length(); int len2 = str2.length(); //前面补0,弄成长度相同 if (len1 < len2) { for (int i = 1; i <= len2 - len1; i++) str1 = "0" + str1; } else { for (int i = 1; i <= len1 - len2; i++) str2 = "0" + str2; } len1 = str1.length(); int cf = 0; int temp; for (int i = len1 - 1; i >= 0; i--) { temp = str1[i] - '0' + str2[i] - '0' + cf; cf = temp / 10; temp %= 10; str = char(temp + '0') + str; } if (cf != 0) str = char(cf + '0') + str; return str; } //高精度减法 //只能是两个正数相减,而且要大减小 string sub(string str1, string str2) //高精度减法 { string str; int tmp = str1.length() - str2.length(); int cf = 0; for (int i = str2.length() - 1; i >= 0; i--) { if (str1[tmp + i] < str2[i] + cf) { str = char(str1[tmp + i] - str2[i] - cf + '0' + 10) + str; cf = 1; } else { str = char(str1[tmp + i] - str2[i] - cf + '0') + str; cf = 0; } } for (int i = tmp - 1; i >= 0; i--) { if (str1[i] - cf >= '0') { str = char(str1[i] - cf) + str; cf = 0; } else { str = char(str1[i] - cf + 10) + str; cf = 1; } } str.erase(0, str.find_first_not_of('0')); //去除结果中多余的前导0 return str; } //高精度乘法 //只能是两个正数相乘 string mul(string str1, string str2) { string str; int len1 = str1.length(); int len2 = str2.length(); string tempstr; for (int i = len2 - 1; i >= 0; i--) { tempstr = ""; int temp = str2[i] - '0'; int t = 0; int cf = 0; if (temp != 0) { for (int j = 1; j <= len2 - 1 - i; j++) tempstr += "0"; for (int j = len1 - 1; j >= 0; j--) { t = (temp * (str1[j] - '0') + cf) % 10; cf = (temp * (str1[j] - '0') + cf) / 10; tempstr = char(t + '0') + tempstr; } if (cf != 0) tempstr = char(cf + '0') + tempstr; } str = add(str, tempstr); } str.erase(0, str.find_first_not_of('0')); return str; } //高精度除法 //两个正数相除,商为quotient,余数为residue //需要高精度减法和乘法 void div(string str1, string str2, string "ient, string &residue) { quotient = residue = ""; //清空 if (str2 == "0") //判断除数是否为0 { quotient = residue = "ERROR"; return; } if (str1 == "0") //判断被除数是否为0 { quotient = residue = "0"; return; } int res = compare(str1, str2); if (res < 0) { quotient = "0"; residue = str1; return; } else if (res == 0) { quotient = "1"; residue = "0"; return; } else { int len1 = str1.length(); int len2 = str2.length(); string tempstr; tempstr.append(str1, 0, len2 - 1); for (int i = len2 - 1; i < len1; i++) { tempstr = tempstr + str1[i]; tempstr.erase(0, tempstr.find_first_not_of('0')); if (tempstr.empty()) tempstr = "0"; for (char ch = '9'; ch >= '0'; ch--) //试商 { string str, tmp; str = str + ch; tmp = mul(str2, str); if (compare(tmp, tempstr) <= 0) //试商成功 { quotient = quotient + ch; tempstr = sub(tempstr, tmp); break; } } } residue = tempstr; } quotient.erase(0, quotient.find_first_not_of('0')); if (quotient.empty()) quotient = "0"; } string gcd(string a, string b) { if (b.empty()) return a; string s, y; div(a, b, s, y); //cout<<a<<" "<<b<<" "<<s<<" "<<y<<endl; return gcd(b, y); } int main() { ios::sync_with_stdio(false); string n, f1, f2; while (cin >> n) { div(n, "2", f1, f2); while (1) { if (gcd(n, f1) == "1") break; f1 = sub(f1, "1"); } cout << f1 << endl; } return 0; }
上下界无源无汇网络流 不能再模版了…
#include<cstdio> #include<iostream> #include<cstring> #include<string> #include<algorithm> #include<cmath> #include<cassert> #include<vector> #include<set> #include<map> #include<queue> using namespace std; const int MAX = 100005; const int INF = 1000000000; struct EDGE { int v, c, next; } edge[1000000]; int E, head[MAX]; int gap[MAX], cur[MAX]; int pre[MAX], dis[MAX]; int in[225], low[50000]; void add_edge(int s, int t, int c, int cc) { edge[E].v = t; edge[E].c = c; edge[E].next = head[s]; head[s] = E++; edge[E].v = s; edge[E].c = cc; edge[E].next = head[t]; head[t] = E++; } int min(int a, int b) { return (a == -1 || b < a) ? b : a; } int SAP(int s, int t, int n) { memset(gap, 0, sizeof(gap)); memset(dis, 0, sizeof(dis)); int i; for (i = 0; i < n; i++) cur[i] = head[i]; int u = pre[s] = s, maxflow = 0, aug = -1, v; gap[0] = n; while (dis[s] < n) { loop: for (i = cur[u]; i != -1; i = edge[i].next) { v = edge[i].v; if (edge[i].c > 0 && dis[u] == dis[v] + 1) { aug = min(aug, edge[i].c); pre[v] = u; cur[u] = i; u = v; if (u == t) { for (u = pre[u]; v != s; v = u, u = pre[u]) { edge[cur[u]].c -= aug; edge[cur[u] ^ 1].c += aug; } maxflow += aug; aug = -1; } goto loop; } } int mindis = n; for (i = head[u]; i != -1; i = edge[i].next) { v = edge[i].v; if (edge[i].c > 0 && dis[v] < mindis) { cur[u] = i; mindis = dis[v]; } } if ((--gap[dis[u]]) == 0) break; gap[dis[u] = mindis + 1]++; u = pre[u]; } return maxflow; } bool solve(int n) { for (int i = 1; i <= n; i++) { if (in[i] > 0) add_edge(0, i, in[i], 0); if (in[i] < 0) add_edge(i, n + 1, -in[i], 0); } SAP(0, n + 1, n + 2); for (int i = head[0]; i != -1; i = edge[i].next) //从源点出发的边都满流 { if (edge[i].c) return false; } return true; } int main() { int n, m, a, b, c; while (~scanf("%d%d", &n, &m)) { E = 0; memset(head, -1, sizeof(head)); memset(in, 0, sizeof(in)); for (int i = 0; i < m; i++) { scanf("%d%d%d%d", &a, &b, &low[i], &c); in[a] -= low[i], in[b] += low[i]; add_edge(a, b, c - low[i], 0); } if (solve(n)) { printf("YES\n"); for (int i = 0; i < m; i++) printf("%d\n", edge[(i << 1) ^ 1].c + low[i]); //反向的流即自由流,再加上下界的流 } else printf("NO\n"); } return 0; }
题可以转化为树上选尽量多的边 选出的边之间没有公共点
树形dp可解
我用dp[i][0.1]表示i这个点的子树的最大值 1表示i点与子树中的点匹配了 0表示没有 我用dp[i][2]表示dp[i][0.1]中的大者 那么转移方程可以很容易的写出
dp[i][0] = sum(dp[v][2]) 其中v表示i的儿子 dp[i][1] = sum(dp[v][2]) - dp[v][2] + dp[v][0] + 1那么这时i和v匹配了
dp的同时记录匹配是很容易的 然后倒着推回去 就可以打印方案了
#include<cstdio> #include<iostream> #include<cstring> #include<string> #include<algorithm> #include<map> #include<set> #include<vector> #include<queue> #include<cstdlib> #include<ctime> #include<cmath> using namespace std; #define N 500010 #define mp(x,y) make_pair(x,y) int n; int dp[N][3], pre[N], ans[N]; int head[N], tot; struct edge { int v, next; } ed[N]; int qu[N]; pair<int, int> que[N]; void add(int u, int v) { ed[tot].v = v; ed[tot].next = head[u]; head[u] = tot++; } void bfs() { int l = 1, r = 2, u, i; qu[1] = 1; while (l < r) { u = qu[l++]; for (i = head[u]; ~i; i = ed[i].next) qu[r++] = ed[i].v; } } int main() { int i, j, k, tmp; while (~scanf("%d", &n)) { tot = 0; memset(head, -1, sizeof(head)); memset(dp, 0, sizeof(dp)); memset(pre, 0, sizeof(pre)); memset(ans, 0, sizeof(ans)); for (i = 2; i <= n; i++) { scanf("%d", &j); add(j, i); } bfs(); for (i = n; i >= 1; i--) { k = 0; for (j = head[i]; ~j; j = ed[j].next) k += dp[ed[j].v][2]; dp[i][0] = k; for (j = head[i]; ~j; j = ed[j].next) { int v = ed[j].v; tmp = k - dp[v][2] + dp[v][0] + 1; if (tmp > dp[i][1]) { pre[i] = v; dp[i][1] = tmp; } } dp[i][2] = max(dp[i][0], dp[i][1]); } printf("%d\n", dp[1][2] * 1000); int l = 1, r = 2; pair<int, int> u, v; if (dp[1][2] == dp[1][1]) que[1] = mp(1,1); else que[1] = mp(1,0); while (l < r) { u = que[l++]; for (i = head[u.first]; ~i; i = ed[i].next) { v.first = ed[i].v; if (v.first == pre[u.first] && u.second) v.second = 0; else { if (dp[v.first][2] == dp[v.first][0]) v.second = 0; else v.second = 1; } que[r++] = v; } if (u.second) ans[pre[u.first]] = 1; } for (i = j = 1; i <= n; i++) { if (ans[i]) { if (j) j = 0; else printf(" "); printf("%d", i); } } printf("\n"); return 0; } }
我不知道什么题 队友说先记个数然后求个和… 反正我就这么写了- -b
#include<cstdio> #include<iostream> #include<cstring> #include<string> #include<algorithm> #include<map> #include<set> #include<vector> #include<queue> #include<cstdlib> #include<ctime> #include<cmath> using namespace std; typedef long long LL; #define inf ((1U<<31)-1) #define N 10010 int n, m; LL ans; int x[N]; int main() { int i, u, v; while (~scanf("%d%d", &n, &m)) { memset(x, 0, sizeof(x)); ans = 0; for (i = 1; i <= m; i++) { scanf("%d%d", &u, &v); x[u]++; x[v]++; } for (i = 1; i <= n; i++) ans += (LL) (x[i]) * x[i]; printf("%lld\n", ans); } return 0; }
一开始以为这题是找循环节 后来发现循环节可能不存在
m很小 所以我们可以利用状压打表 这样形成了一个矩阵 矩阵中(i,j)=1表示能从i状态转到j状态 我们发现这个矩阵是始终不变的 换句话说就是初始状态根据这个矩阵做n次操作 这种事明显可以快速幂来搞 正好前面写过高精度 拿来直接改 1A神马的还是稳稳地 ~~
#include<cstdio> #include<iostream> #include<cstring> #include<string> #include<algorithm> #include<map> #include<set> #include<vector> #include<queue> #include<cstdlib> #include<ctime> #include<cmath> using namespace std; string n; int m, p; int k[32][32]; int bin[10]; //高精度 //compare比较函数:相等返回0,大于返回1,小于返回-1 int compare(string str1, string str2) { if (str1.length() > str2.length()) return 1; else if (str1.length() < str2.length()) return -1; else return str1.compare(str2); } //高精度加法 //只能是两个正数相加 string add(string str1, string str2) //高精度加法 { string str; int len1 = str1.length(); int len2 = str2.length(); //前面补0,弄成长度相同 if (len1 < len2) { for (int i = 1; i <= len2 - len1; i++) str1 = "0" + str1; } else { for (int i = 1; i <= len1 - len2; i++) str2 = "0" + str2; } len1 = str1.length(); int cf = 0; int temp; for (int i = len1 - 1; i >= 0; i--) { temp = str1[i] - '0' + str2[i] - '0' + cf; cf = temp / 10; temp %= 10; str = char(temp + '0') + str; } if (cf != 0) str = char(cf + '0') + str; return str; } //高精度减法 //只能是两个正数相减,而且要大减小 string sub(string str1, string str2) //高精度减法 { string str; int tmp = str1.length() - str2.length(); int cf = 0; for (int i = str2.length() - 1; i >= 0; i--) { if (str1[tmp + i] < str2[i] + cf) { str = char(str1[tmp + i] - str2[i] - cf + '0' + 10) + str; cf = 1; } else { str = char(str1[tmp + i] - str2[i] - cf + '0') + str; cf = 0; } } for (int i = tmp - 1; i >= 0; i--) { if (str1[i] - cf >= '0') { str = char(str1[i] - cf) + str; cf = 0; } else { str = char(str1[i] - cf + 10) + str; cf = 1; } } str.erase(0, str.find_first_not_of('0')); //去除结果中多余的前导0 return str; } //高精度乘法 //只能是两个正数相乘 string mul(string str1, string str2) { string str; int len1 = str1.length(); int len2 = str2.length(); string tempstr; for (int i = len2 - 1; i >= 0; i--) { tempstr = ""; int temp = str2[i] - '0'; int t = 0; int cf = 0; if (temp != 0) { for (int j = 1; j <= len2 - 1 - i; j++) tempstr += "0"; for (int j = len1 - 1; j >= 0; j--) { t = (temp * (str1[j] - '0') + cf) % 10; cf = (temp * (str1[j] - '0') + cf) / 10; tempstr = char(t + '0') + tempstr; } if (cf != 0) tempstr = char(cf + '0') + tempstr; } str = add(str, tempstr); } str.erase(0, str.find_first_not_of('0')); return str; } //高精度除法 //两个正数相除,商为quotient,余数为residue //需要高精度减法和乘法 void div(string str1, string str2, string "ient, string &residue) { quotient = residue = ""; //清空 if (str2 == "0") //判断除数是否为0 { quotient = residue = "ERROR"; return; } if (str1 == "0") //判断被除数是否为0 { quotient = residue = "0"; return; } int res = compare(str1, str2); if (res < 0) { quotient = "0"; residue = str1; return; } else if (res == 0) { quotient = "1"; residue = "0"; return; } else { int len1 = str1.length(); int len2 = str2.length(); string tempstr; tempstr.append(str1, 0, len2 - 1); for (int i = len2 - 1; i < len1; i++) { tempstr = tempstr + str1[i]; tempstr.erase(0, tempstr.find_first_not_of('0')); if (tempstr.empty()) tempstr = "0"; for (char ch = '9'; ch >= '0'; ch--) //试商 { string str, tmp; str = str + ch; tmp = mul(str2, str); if (compare(tmp, tempstr) <= 0) //试商成功 { quotient = quotient + ch; tempstr = sub(tempstr, tmp); break; } } } residue = tempstr; } quotient.erase(0, quotient.find_first_not_of('0')); if (quotient.empty()) quotient = "0"; } //快速幂 const int mat_n = 32; void matrix_mul(int a[][mat_n], int b[][mat_n]) { int c[mat_n][mat_n]; int i, j, k; for (i = 0; i < mat_n; i++) { for (j = 0; j < mat_n; j++) { c[i][j] = 0; for (k = 0; k < mat_n; k++) { c[i][j] = (c[i][j] + (a[i][k] * b[k][j]) % p) % p; } } } for (i = 0; i < mat_n; i++) for (j = 0; j < mat_n; j++) a[i][j] = c[i][j]; } void matrix_power(int s[][mat_n]) { int ans[mat_n][mat_n]; memset(ans, 0, sizeof(ans)); int i, j; for (i = 0; i < mat_n; i++) ans[i][i] = 1; string sh, yu; while (compare(n, "0") != 0) { div(n, "2", sh, yu); if (yu == "1") matrix_mul(ans, s); n = sh; matrix_mul(s, s); } for (i = 0; i < mat_n; i++) for (j = 0; j < mat_n; j++) s[i][j] = ans[i][j]; } int main() { ios::sync_with_stdio(false); int i, j, f, flag; bin[0] = 1; for (f = 1; f < 10; f++) bin[f] = bin[f - 1] << 1; while (cin >> n >> m >> p) { for (i = 0; i < bin[m]; i++) { for (j = 0; j < bin[m]; j++) { flag = 1; for (f = 0; f < m - 1; f++) { if (((i & bin[f]) == (j & bin[f]) && (i & bin[f + 1]) == (j & bin[f + 1]) && ((i & bin[f]) << 1) == (j & bin[f + 1]))) { flag = 0; break; } } k[i][j] = flag; //printf("%d ", flag); } //printf("\n"); } n = sub(n, "1"); matrix_power(k); f = 0; for (i = 0; i < bin[m]; i++) { for (j = 0; j < bin[m]; j++) f += k[i][j]; } printf("%d\n", f % p); } return 0; }
唯一一道没做出的题 题解看这http://www.cppblog.com/Yuan/archive/2010/05/02/114163.html
当时我们的思路就卡在“将视角当作边权”这里 这个想法很是巧妙
G:
我犯二的题 我一开始想 按照不讨厌来建边 然后最大团就是答案 但是点这么多… 这时队友说 “简单的二维不降子序列题”… 这才顿悟… 不讨厌就是S和B都大 那么不就是标准的模型了…
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int dp[100010],mark[100010],cnt[100010]; const int inf=1e9; struct node{ int x,y,idx; bool operator < (const node &a) const{ return x<a.x||(x==a.x&&y>a.y); } }p[100010]; int main() { int n,t,x,y,ans; int i; while(scanf("%d",&n)!=EOF) { ans=0; //printf("n.%d\n",n); for(i=0;i<n;i++){ scanf("%d%d",&x,&y); //printf("u.........%d\n",i); p[i].x=x; p[i].y=y; p[i].idx=i+1; } sort(p,p+n); for(i=0;i<n;i++) dp[i]=inf; for(i=0;i<n;i++){ int tmp=lower_bound(dp,dp+n,p[i].y)-dp; dp[tmp]=p[i].y; mark[i]=tmp; ans=max(ans,tmp); } printf("%d\n",ans+1); int tot=0; for(i=n-1;i>=0;i--){ if(mark[i]==ans){ cnt[tot++]=p[i].idx; ans--; } } sort(cnt,cnt+tot); for(i=0;i<tot;i++) { printf("%d",cnt[i]); if(i==tot-1) printf("\n"); else printf(" "); } } return 0; }
不知道题… 队友直接就给A了… 我就贴代码吧 - -b
#include<stdio.h> #include<algorithm> #include<iostream> #include<string.h> #include<math.h> using namespace std; typedef long long ll; const int MAXN = 110; #define MAX 2010 #define mod 10000 #define baselen 4 #define in(a) scanf("%d",&a) #define out1(a) printf("%d",a) #define out2(a) printf("%04d",a) int a[MAXN][MAXN]; //增广矩阵 int x[MAXN]; //解集 bool free_x[MAXN]; //标记是否是不确定的变元 inline int abs(int a) { return a > 0 ? a : -a; } void Debug(int equ, int var) { int i, j; for (i = 0; i < equ; i++) { for (j = 0; j < var + 1; j++) { cout << a[i][j] << " "; } cout << endl; } cout << endl; } //m个方程,n个变量!! int rank(int A[MAXN][MAXN], int m, int n) //求解01模2方程的秩!! { int i = 0, j = 0, k, r, u; while (i < m && j < n) //当前正在处理第i行,第j个变量!! { r = i; for (k = i; k < m; k++) if (A[k][j]) { r = k; break; } if (A[r][j]) { if (r != i) for (k = 0; k <= n; k++) swap(A[r][k], A[i][k]); for (u = i + 1; u < m; u++) if (A[u][j]) for (k = i; k <= n; k++) A[u][k] ^= A[i][k]; i++; } j++; } return i; //系数矩阵的秩! } int p[1000], flag[1000], cnt = 0; void get_prime() { int i, j; for (i = 2; i < 600; i++) { if (!flag[i]) p[cnt++] = i; ; for (j = 0; j < cnt && p[j] * i < 600; j++) { flag[i * p[j]] = 1; if (i % p[j] == 0) break; } } } int b[200]; typedef int type; ///////////////////////////////////// struct bint { type dig[MAX], len; bint() { len = 0, dig[0] = 0; } }; //////////////////////////////////////////// //常用函数 //(1) void add(bint a, bint b, bint& c) { type i, carry; for (i = carry = 0; i <= a.len || i <= b.len || carry; i++) { if (i <= a.len) carry += a.dig[i]; if (i <= b.len) carry += b.dig[i]; c.dig[i] = carry % mod; carry /= mod; } c.len = i - 1; } //(2) void add(bint a, type b, bint& c) { type i; for (i = 0; i <= a.len || b; i++) { if (i <= a.len) b += a.dig[i]; c.dig[i] = b % mod; b /= mod; } c.len = i - 1; } //(3) void by(bint a, type b, bint& c) { type i, carry; for (i = carry = 0; i <= a.len || carry; i++) { if (i <= a.len) carry += b * a.dig[i]; c.dig[i] = carry % mod; carry /= mod; } i--; while (i && !c.dig[i]) i--; c.len = i; } //(4) void by(bint a, bint b, bint& c) { type i, j, carry; for (i = a.len + b.len + 1; i >= 0; i--) c.dig[i] = 0; for (i = 0; i <= a.len; i++) { carry = 0; for (j = 0; j <= b.len || carry; j++) { carry += c.dig[i + j]; if (j <= b.len) carry += a.dig[i] * b.dig[j]; c.dig[i + j] = carry % mod; carry /= mod; } } i = a.len + b.len + 1; while (i && c.dig[i] == 0) i--; c.len = i; } //(5) void div(bint a, type b, bint& c, type& d) { type i; for (i = a.len, d = 0; i >= 0; i--) { d = d * mod + a.dig[i]; c.dig[i] = d / b; d = d % b; } i = a.len; while (i && c.dig[i] == 0) i--; c.len = i; } //(6) bool input(bint& a) { type i, j, w, k, p; char data[MAX * baselen + 1]; if (scanf("%s", data) == EOF) return false; w = strlen(data) - 1, a.len = 0; for (p = 0; p <= w && data[p] == '0'; p++) ; while (1) { i = j = 0, k = 1; while (i < baselen && w >= p) { j = j + (data[w--] - '0') * k; k *= 10, i++; } a.dig[a.len++] = j; if (w < p) break; } a.len--; return true; } //(7) void output(bint& a) { type i; i = a.len - 1; out1(a.dig[a.len]); while (i >= 0) out2(a.dig[i--]); printf("\n"); } //////////////////////////////////////////////////////////////////////// //少用函数 //(8) void move(bint& a) { type carry, k, t; k = a.len + 1, carry = 0; while (k--) { t = a.dig[k] & 1; a.dig[k] = (a.dig[k] >> 1); if (carry) a.dig[k] += (mod >> 1); carry = t; } if (a.len && a.dig[a.len] == 0) a.len--; } //(9) void sub(bint a, bint b, bint& c) { type i, carry; for (i = carry = 0; i <= a.len; i++) { c.dig[i] = a.dig[i] - carry; if (i <= b.len) c.dig[i] -= b.dig[i]; if (c.dig[i] < 0) carry = 1, c.dig[i] += mod; else carry = 0; } i--; while (i && c.dig[i] == 0) i--; c.len = i; } //(10) void sub(bint a, type b, bint& c) { type i; for (i = 0; i <= a.len; i++) { c.dig[i] = a.dig[i] - b; if (c.dig[i] < 0) b = 1, c.dig[i] += mod; else b = 0; } i--; while (i && c.dig[i] == 0) i--; c.len = i; } //(11) int cmp(bint a, bint b) { if (a.len < b.len) return -1; if (a.len > b.len) return 1; int i = a.len; while (i && a.dig[i] == b.dig[i]) i--; return a.dig[i] - b.dig[i]; } //(12) void give(bint a, bint& b) { int i = 0; while (i <= a.len) { b.dig[i] = a.dig[i]; i++; } b.len = a.len; } //(13) void give(type a, bint& b) { b.dig[0] = a % mod; a /= mod; if (a > 0) b.dig[1] = a, b.len = 1; else b.len = 0; } //(14) void shift(bint& a, type k) { int i; i = a.len + k; while (i >= k) { a.dig[i] = a.dig[i - k]; i--; } while (i >= 0) a.dig[i--] = 0; a.len += k; } //(15) void div(bint a, bint b, bint& c, bint& d) { type x, k; bint temp; give(a, d); c.len = c.dig[0] = 0; while (cmp(d, b) > 0) { k = d.len - b.len; if (d.dig[d.len] > b.dig[b.len]) x = d.dig[d.len] / (b.dig[b.len] + 1); else if (k) k--, x = (d.dig[d.len] * mod + d.dig[d.len - 1]) / (b.dig[b.len] + 1); else break; by(b, x, temp); shift(temp, k); sub(d, temp, d); give(x, temp); shift(temp, k); add(c, temp, c); } if (cmp(d, b) >= 0) sub(d, b, d), add(c, (type) 1, c); } int main() { get_prime(); //for(int i=0;i<=100;i++)printf("%d %d\n",i+1,p[i]); int i, j, t, m; while (~scanf("%d%d", &t, &m)) { int xx; memset(a, 0, sizeof(a)); for (i = 0; i < m; i++) { scanf("%d", &xx); for (j = 0; j < t; j++) while (xx % p[j] == 0) { xx /= p[j]; a[j][i] ^= 1; } } //Debug(maxp+1,n); int r = rank(a, t, m); int y = m - r; if (y < 64) { ll ans = (1LL << y) - 1; printf("%lld\n", ans); continue; } bint tmp, Ans; give(1, Ans); while (y--) { tmp = Ans; by(tmp, 2, Ans); } tmp = Ans; sub(tmp, 1, Ans); output(Ans); } return 0; }