您的位置:首页 > 其它

UVA 12298 Super Poker II(FFT)

2017-08-07 17:39 429 查看
题目链接:点击打开链接

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 c ≤ 10, 000. For other test cases, 1 ≤ a ≤ b ≤ 100, 0 ≤ c ≤ 10.

Output

For each test case, print p 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

题意:从4种扑克牌中各选出一个合数,能构成点数为n的方案数。但是有一些牌是缺失了的。

要求输出从a-b之间所有数的方案数。

很容易看出来是4个数组的卷积,求出卷积之后输出就行了。主要要用long double。

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#define LL long long

using namespace std;

const long double PI = acos(-1.0);
//复数结构体
struct complex
{
long double r,i;
complex(long double _r = 0.0,long double _i = 0.0)
{
r = _r; i = _i;
}
complex operator +(const complex &b)
{
return complex(r+b.r,i+b.i);
}
complex operator -(const complex &b)
{
return complex(r-b.r,i-b.i);
}
complex operator *(const complex &b)
{
return complex(r*b.r-i*b.i,r*b.i+i*b.r);
}
};
/*
* 进行FFT和IFFT前的反转变换。
* 位置i和 (i二进制反转后位置)互换
* len必须去2的幂
*/
void change(complex y[],int len)
{
int i,j,k;
for(i = 1, j = len/2;i < len-1; i++)
{
if(i < j)swap(y[i],y[j]);
//交换互为小标反转的元素,i<j保证交换一次
//i做正常的+1,j左反转类型的+1,始终保持i和j是反转的
k = len/2;
while(j >= k)
{
j -= k;
k /= 2;
}
if(j < k) j += k;
}
}
/*
* 做FFT
* len必须为2^k形式,
* on==1时是DFT,on==-1时是IDFT
*/
void fft(complex y[],int len,int on)
{
change(y,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 = y[k];
complex 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 < len;i++)
y[i].r /= len;
}
const int MAXN = 800040;
complex x1[MAXN],x2[MAXN],x3[MAXN],x4[MAXN];

int flag[50010];

void prime()
{
LL i,j;
for(i=2;i<50010;i++)
{
if(flag[i])
continue;
for(j=i*i;j<50010;j+=i)
{
flag[j] = 1;
}
}
}

int main(void)
{
prime();
int a,b,c,i,j;
char s[100];
while(scanf("%d%d%d",&a,&b,&c)==3)
{
if(!a && !b && !c)
break;
int len = 1;
while(len <= 4*b)
len <<= 1;
for(i=0;i<=b;i++)
x1[i] = x2[i] = x3[i] = x4[i] = complex(flag[i],0);
for(i=b+1;i<len;i++)
x1[i] = x2[i] = x3[i] = x4[i] = complex(0,0);
for(i=0;i<c;i++)
{
scanf("%s",s);
int l = strlen(s);
int x = 0;
for(j=0;j<l-1;j++)
x = x*10+s[j]-'0';
if(s[l-1] == 'S')
x1[x] = complex(0,0);
if(s[l-1] == 'H')
x2[x] = complex(0,0);
if(s[l-1] == 'C')
x3[x] = complex(0,0);
if(s[l-1] == 'D')
x4[x] = complex(0,0);
}
fft(x1,len,1);
fft(x2,len,1);
fft(x3,len,1);
fft(x4,len,1);
for(i=0;i<len;i++)
x1[i] = x1[i]*x2[i]*x3[i]*x4[i];
fft(x1,len,-1);

for(i=a;i<=b;i++)
printf("%lld\n",(LL)(x1[i].r+0.5));
printf("\n");
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: