ACdream Andrew Stankevich's Contest(1)

来源:互联网 发布:windows安装淘宝镜像 编辑:程序博客网 时间:2024/05/25 21:34

国庆打了场组队  效果还不错  季军  现在发下题解

A:

高精度模拟即可  与n互素的数不会离n/2太远  直接暴力

代码:

#include<stdio.h>#include<string>#include<string.h>#include<iostream>using namespace std; //compare比较函数:相等返回0,大于返回1,小于返回-1int 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,小于返回-1int 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;}


0 0
原创粉丝点击