[Hackrank] Prime XOR (计数DP)

来源:互联网 发布:hp扫描仪软件 编辑:程序博客网 时间:2024/05/29 18:48

Hackrank - Prime XOR

给定N个数,求有多少个不同子集的异或和为质数
其中 N105,3500ai4500

首先异或和不会超过 2131
然后虽然 N 很大,但是每个数的范围在1000以内
所以总的不同的数不会很多
所以做法是枚举每种数取了多少个,然后暴力转移即可
刚开始我枚举的部分用的是组合数,但这是不对的
因为他要求不同子集,所以只要个数一定就不管他是从哪个位置取的
所以只要统计出每种数取奇数个的取法和取偶数个的取法转移即可

#pragma comment(linker, "/STACK:102400000,102400000")#include <cstdio>#include <iostream>#include <cstdlib>#include <cstring>#include <algorithm>#include <cmath>#include <cctype>#include <map>#include <set>#include <queue>#include <bitset>#include <string>#include <cassert>#include <complex>using namespace std;typedef pair<int,int> Pii;typedef long long LL;typedef unsigned long long ULL;typedef double DBL;typedef long double LDBL;#define MST(a,b) memset(a,b,sizeof(a))#define CLR(a) MST(a,0)#define SQR(a) ((a)*(a))#define PCUT puts("\n----------")#define PRI(x) cout << #x << ": " << (x) << endl#define PPR(x,y) cout << #x << " " << #y << ": " << (x) << " " << (y) << endlconst int maxn=1e5+5, maxi=4500+5, MOD=1e9+7, maxv=1<<13;int N;int in[maxi];LL dp[2][maxv];bool sieve[maxv];int main(){    #ifdef LOCAL    freopen("in.txt", "r", stdin);//  freopen("out.txt", "w", stdout);    #endif    for(int i=2; i<maxv; i++) if(!sieve[i])        for(int j=i*i; j<maxv; j+=i) sieve[j]=1;    int T;    scanf("%d", &T);    for(int ck=1; ck<=T; ck++)    {        scanf("%d", &N);        CLR(in);        for(int i=1,x; i<=N; i++)        {            scanf("%d", &x);            in[x]++;        }        CLR(dp);        int now=0,las=1;        dp[now][0] = 1;        for(int i=3500; i<=4500; i++) if(in[i])        {            now^=1; las^=1;            CLR(dp[now]);            for(int j=0; j<maxv; j++)            {                dp[now][j] = ( dp[now][j] + (in[i]/2+1)*dp[las][j]%MOD)%MOD;                dp[now][j^i] = ( dp[now][j^i] + ((in[i]-1)/2+1)*dp[las][j]%MOD)%MOD;            }        }        LL ans=0;        for(int i=2; i<maxv; i++) if(!sieve[i] && dp[now][i])        {            ans = (ans+dp[now][i])%MOD;//          if(dp[now][i]) printf("%d %lld\n", i, dp[now][i]);        }        printf("%lld\n", ans);    }    return 0;}
原创粉丝点击