ACdream Andrew Stankevich's Contest(1)

47 篇文章 0 订阅
43 篇文章 0 订阅

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

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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值