【UVa12298】 Super Joker II 【FFT】【生成函数】

居然因为精度问题WA掉了。。。
这题要用long double,并且交c++11……
每种花色的牌开一个系数向量,有这种牌那么系数就是1,否则为0.然后FFT乘起来就行了。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std;
typedef long double real;
const int maxn=262144;
const real pi=acos(-1.0);
//3.1415926535897932384626433832795028841971693993751058209749445923806406;
struct cp{
    real r,i;
    cp(real _r=0.,real _i=0.):r(_r),i(_i){}
    cp operator+(const cp &a){
        return cp(r+a.r,i+a.i);
    }
    cp operator-(const cp &a){
        return cp(r-a.r,i-a.i);
    }
    cp operator*(const cp &a){
        return cp(r*a.r-i*a.i,r*a.i+i*a.r);
    }
}s[maxn],h[maxn],c[maxn],d[maxn];
int prime[30000],tot;
bool isprime[50001];
void brc(cp y[],int len){
    for(int i=1,j=len>>1;i<len-1;++i){
        if(i<j) swap(y[i],y[j]);
        int k=len>>1;
        while(j>=k) j-=k,k>>=1;
        j+=k;
    }
}
void fft(cp y[],int l,int on){
    brc(y,l);
    int j,k,h;
    cp u,t;
    for(h=2;h<=l;h<<=1){
        cp wn(cos(on*2*pi/h),sin(on*2*pi/h));
        for(int j=0;j<l;j+=h){
            cp w(1);
            for(int k=j;k<j+h/2;++k){
                u=y[k];
                t=w*y[k+h/2];
                y[k]=u+t;
                y[k+h/2]=u-t;
                w=w*wn;
            }
        }
    }
    if(on==-1) for(int i=0;i<l;++i) y[i].r/=l;
}
void genPrime(int n){
    memset(isprime,true,sizeof isprime);
    for(int i=2;i<=n;++i){
        if(isprime[i])
            prime[tot++]=i;
        for(int j=0;j<tot&&i*prime[j]<=n;++j){
            isprime[i*prime[j]]=false;
            if(i%prime[j]==0) break;
        }
    }
}
void print(long long x){
    char a[20]={0};
    if(!x) a[0]=1;
    while(x) a[++a[0]]=x%10,x/=10;
    for(;a[0];--a[0])
        putchar(a[a[0]]+48);
    putchar('\n');
}
int main(){
    int A,B,C;
    genPrime(50000);
    while(scanf("%d%d%d",&A,&B,&C)==3&&(A||B||C)){
        int L=1;
        while(L<=B) L<<=1;
        L<<=2;
        memset(s,0,sizeof s);
        memset(h,0,sizeof h);
        memset(c,0,sizeof c);
        memset(d,0,sizeof d);
        for(int i=0;i<B;++i) if(!isprime[i]) s[i].r=1;
        for(int i=0;i<B;++i) if(!isprime[i]) h[i].r=1;
        for(int i=0;i<B;++i) if(!isprime[i]) c[i].r=1;
        for(int i=0;i<B;++i) if(!isprime[i]) d[i].r=1;

        for(int i=0;i<C;++i){
            char str[20];
            scanf("%s",str);
            int len=strlen(str),t;
            sscanf(str,"%d",&t);
            switch(str[len-1]){
                case 'S':s[t].r=0;break;
                case 'H':h[t].r=0;break;
                case 'C':c[t].r=0;break;
                case 'D':d[t].r=0;break;
            }
        }

        fft(s,L,1);fft(h,L,1);
        fft(c,L,1);fft(d,L,1);
        for(int i=0;i<L;++i) h[i]=s[i]*h[i]*c[i]*d[i];
        fft(h,L,-1);
        for(int i=A;i<=B;++i) printf("%.0lf\n",fabs((double)h[i].r));
        putchar('\n');
    }
    return 0;
}

I have a set of super poker cards, consisting of an infinite number of cards. For each positive composite integer p , there are exactly four cards whose value is p: Spade(S),Heart(H),Club(C) and Diamond(D) . There are no cards of other values. By “composite integer”, we mean integers that have more than 2 divisors. For example, 6 is a composite integer, since it has 4 divisors: 1,2,3,6; 7 is not a composite number, since 7 only has 2 divisors: 1 and 7 . Note that 1 is not composite (it has only 1 divisor). Given a positive integer n , how many ways can you pick up exactly one card from each suit (i.e. exactly one spade card, one heart card, one club card and one diamond card), so that the card values sum to n? For example, if n=24 , one way is 4S+6H+4C+10D , shown below:

这里写图片描述
Unfortunately, some of the cards are lost, but this makes the problem more interesting. To further make the problem even more interesting (and challenging!), I’ll give you two other positive integers a and b, and you need to find out all the answers for n=a,n=a+1,...,n=b .
Input
The input contains at most 25 test cases. Each test case begins with 3 integers a, b and c, where c is the number of lost cards. The next line contains c strings, representing the lost cards. Each card is formatted as valueS,valueH,valueC or valueD , where value is a composite integer. No two lost cards are the same. The input is terminated by a=b=c=0 . There will be at most one test case where a=1,b=50,000 and c10,000 . For other test cases, 1ab100,0c10 .
Output
For each test case, print p (应为ba+1) integers, one in each line. Print a blank line after each test case.
Sample Input
12 20 2
4S 6H
0 0 0
Sample Output
0
0
0
0
0
0
1
0
3

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值