UVA 12298 Super Poker II

来源:互联网 发布:java http 幂等 编辑:程序博客网 时间:2024/06/08 15:52

转载请注明出处,谢谢http://blog.csdn.net/bigtiao097?viewmode=contents

题意

给定一些扑克牌,value为合数,其中丢了c张牌,问这些扑克牌选四色(必须一个花色选一张)能组成n的方案数

思路

素筛,然后构造四个多项式(每个花色一个),去掉丢失的牌
将这四个多项式相乘,利用FFT,得到的就是方案数了
注意:精度会爆double,要用long double
最后结果会爆int,要用long long
输出不能用%I64d,要用%lld


Result: Accepted Time: 170ms
具体代码如下:

#include<bits/stdc++.h>using namespace std;typedef long long ll;const long double PI = acos(-1);const int maxn = 5e4+5;//maxn = max(len1,len2)const int maxm = 4*maxn;//k是>=maxn的最小的2的幂,maxm=2*kint len1,len2,len;//len1,len2分别为两个多项式的最高次数+1ll S[maxn],H[maxn],C[maxn],D[maxn];char str[20];ll num1[maxm],num2[maxm];ll ans[maxm];bool vis[maxn];int a,b,c,x,y;void sieve(){    int m = sqrt(maxn+0.5);    memset(vis, 0, sizeof vis);    for(int i = 2; i <= m; i++) if(!vis[i])        for(int j = i*i; j < maxn; j+=i) vis[j] = 1;}//复数结构体struct Complex{    long double x, y;//实部为x,虚部为y    Complex(long double x=0,long double y=0):x(x),y(y){}    Complex operator+(const Complex &rhs) const { return Complex(x+rhs.x, y+rhs.y);}    Complex operator-(const Complex &rhs) const { return Complex(x-rhs.x, y-rhs.y);}    Complex operator*(const Complex &rhs) const { return Complex(x*rhs.x-y*rhs.y,x*rhs.y+y*rhs.x);}};Complex x1[maxm],x2[maxm];/*进行FFT和IFFT前的反转变换。将位置i和(i二进制反转后位置)互换。len必须取2的幂*/void change(Complex *x, int len){    Complex t;    for(int i = 1, j = len/2; i < len-1; i++)    {        //交换下标互反的元素,i<j保证交换一次        //i做正常的+1,j做反转的+1,始终保持i和j是反转的        if(i < j)        {            t = x[i];            x[i] = x[j];            x[j] = t;        }        int k = len / 2;        while(j >= k)        {            j -= k;            k >>= 1;        }        if(j < k) j += k;    }}/*做FFTlen必须为2的幂on==1时是DFT,on==-1时是IDFT*/void fft(Complex *x, int len, int on){    change(x, len);    for(int h = 2; h <= len; h <<= 1)    {        Complex wn(cos(-on*2*PI/h), sin(-on*2*PI/h));        for(int j = 0; j < len; j += h)        {            Complex w(1, 0);            for(int k = j; k < j+h/2; k++)            {                Complex u = x[k];                Complex t = w*x[k+h/2];                x[k] = u+t;                x[k+h/2] = u-t;                w = w*wn;            }        }    }    if(on == -1)        for(int i = 0; i < len; i++) x[i].x /= len;}void workFFT(ll *xx,int len1,ll *yy,int len2,ll *num){    len = 1;    memset(x1,0,sizeof x1);    memset(x2,0,sizeof x2);    memset(num,0,sizeof num);    while(len < len1*2 || len < len2*2) len <<=1;    for(int i = 0; i < len; i++)            x1[i] =  x2[i] = Complex(0,0);    for(int i = 0; i < len1; i++) x1[i] = Complex(xx[i],0);    for(int i = 0; i < len2; i++) x2[i] = Complex(yy[i],0);    fft(x1,len,1);    fft(x2,len,1);    for(int i = 0; i < len; i++) x1[i] = x1[i]*x2[i];    fft(x1,len,-1);    for(int i = 0; i < len; i++) num[i] = (ll)(x1[i].x+0.5);}int main(){    sieve();    while(~scanf("%d%d%d",&a,&b,&c),a+b+c)    {        for(int i=2;i<=b;i++)            if(vis[i])        {            //cout<<i<<endl;            S[i]=1;            H[i]=1;            C[i]=1;            D[i]=1;        }        for(int i=1;i<=c;i++)        {            scanf("%s",str);            x = strlen(str);            y = str[0]-'0';            for(int i=1;i<x-1;i++)                y = y*10 + str[i]-'0';            if(str[x-1]=='H') H[y]=0;            if(str[x-1]=='S') S[y]=0;            if(str[x-1]=='C') C[y]=0;            if(str[x-1]=='D') D[y]=0;        }        workFFT(H,b+1,S,b+1,num1);        workFFT(C,b+1,D,b+1,num2);        workFFT(num1,b+1,num2,b+1,ans);        for(int i=a;i<=b;i++)            printf("%lld\n",ans[i]);        printf("\n");    }}