【来源】http://blog.csdn.net/houserabbit/article/details/39719063
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;
- }
B:
上下界无源无汇网络流 不能再模版了…
- #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;
- }
C:
题可以转化为树上选尽量多的边 选出的边之间没有公共点
树形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;
- }
- }
D:
我不知道什么题 队友说先记个数然后求个和… 反正我就这么写了- -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;
- }
E:
一开始以为这题是找循环节 后来发现循环节可能不存在
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;
- }
F:
唯一一道没做出的题 题解看这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;
- }
H:
不知道题… 队友直接就给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;
- }