UVA 12298 Super Poker II (FFT)

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;

const int N = 1000005;
const long double pi = acos(-1.0);

struct Complex
{
    long double r,i;
    Complex(long double r=0, long double i=0):r(r),i(i) {};
    Complex operator+(const Complex &rhs)
    {
        return Complex(r + rhs.r,i + rhs.i);
    }
    Complex operator-(const Complex &rhs)
    {
        return Complex(r - rhs.r,i - rhs.i);
    }
    Complex operator*(const Complex &rhs)
    {
        return Complex(r*rhs.r - i*rhs.i,i*rhs.r + r*rhs.i);
    }
} pS[N], pH[N], pC[N], pD[N];
//len = 2^M,reverse F[i] with  F[j] j为i二进制反转
void rader(Complex F[],int len)
{
    int j = len >> 1;
    for(int i = 1; i < len - 1; ++i)
    {
        if(i < j) swap(F[i],F[j]);  // reverse
        int k = len>>1;
        while(j>=k)
        {
            j -= k;
            k >>= 1;
        }
        if(j < k) j += k;
    }
}

void FFT(Complex F[],int len,int t)
{
    rader(F,len);
    for(int h=2; h<=len; h<<=1)
    {
        Complex wn(cos(-t*2*pi/h),sin(-t*2*pi/h));
        for(int j=0; j<len; j+=h)
        {
            Complex E(1,0); //旋转因子
            for(int k=j; k<j+h/2; ++k)
            {
                Complex u = F[k];
                Complex v = E*F[k+h/2];
                F[k] = u+v;
                F[k+h/2] = u-v;
                E=E*wn;
            }
        }
    }
    if(t==-1)   //IDFT
        for(int i=0; i<len; ++i)
            F[i].r/=len;
}

void Conv(Complex a[],Complex b[],int len) //求卷积
{
    FFT(a,len,1);
    FFT(b,len,1);
    for(int i=0; i<len; ++i) a[i] = a[i]*b[i];
    FFT(a,len,-1);
}

long prime[N] = {0},num_prime = 0;
int isNotPrime[N] = {1, 1};
void init()
{
    for(long i = 2 ; i < N ; i ++)
    {
        if(! isNotPrime[i])
            prime[num_prime ++]=i;
        for(long j = 0 ; j < num_prime && i * prime[j] <  N ; j ++)
        {
            isNotPrime[i * prime[j]] = 1;
            if( !(i % prime[j] ) )
                break;
        }
    }
}

int main()
{
    int A, B, C;
    init();
    while(scanf("%d%d%d", &A, &B, &C) && (A+B+C))
    {
        memset(pS, 0, sizeof(pS));
        memset(pH, 0, sizeof(pH));
        memset(pC, 0, sizeof(pC));
        memset(pD, 0, sizeof(pD));
        for(int i=2; i<=B; ++i)
            if(isNotPrime[i])
                pS[i]=pH[i]=pC[i]=pD[i]=Complex(1);
        int len=1;
        while(len<B) len<<=1;
        len<<=3;
        while(C--)
        {
            int v;
            char type;
            scanf("%d%c", &v, &type);
            switch(type)
            {
                case ‘S‘:pS[v]=Complex(0);break;
                case ‘H‘:pH[v]=Complex(0);break;
                case ‘C‘:pC[v]=Complex(0);break;
                case ‘D‘:pD[v]=Complex(0);break;
            }
        }
        FFT(pS, len, 1), FFT(pH, len, 1), FFT(pC, len, 1), FFT(pD, len, 1);
        for(int i=0; i<len; ++i)
            pS[i]=pS[i]*pH[i]*pC[i]*pD[i];
        FFT(pS, len, -1);
        for(int i=A; i<=B; ++i)
            printf("%lld\n", (long long)(pS[i].r+0.5));
        puts("");
    }
    return 0;
}
时间: 2024-12-12 09:37:26

UVA 12298 Super Poker II (FFT)的相关文章

UVa12298 Super Poker II(母函数 + FFT)

题目 Source http://acm.hust.edu.cn/vjudge/problem/23590 Description 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),

bzoj2487: Super Poker II

Description 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 va

UVA 10869 - Brownie Points II(树状数组)

UVA 10869 - Brownie Points II 题目链接 题意:平面上n个点,两个人,第一个人先选一条经过点的垂直x轴的线,然后另一个人在这条线上穿过的点选一点作垂直该直线的线,然后划分出4个象限,第一个人得到分数为1,3象限,第二个人为二四象限,问第一个个人按最优取法,能得到最小分数的最大值,和这个值下另一个人的得分可能情况 思路:树状数组,可以枚举一点,如果能求出右上和左下点的个数就好办了,其实用一个树状数组,把y坐标离散化掉,然后记录进来,然后把点按x从左往右,每次删掉点后查询

UVA 11426 - GCD - Extreme (II) (数论)

UVA 11426 - GCD - Extreme (II) 题目链接 题意:给定N,求∑i<=ni=1∑j<nj=1gcd(i,j)的值. 思路:lrj白书上的例题,设f(n) = gcd(1, n) + gcd(2, n) + ... + gcd(n - 1, n).这样的话,就可以得到递推式S(n) = f(2) + f(3) + ... + f(n) ==> S(n) = S(n - 1) + f(n);. 这样问题变成如何求f(n).设g(n, i),表示满足gcd(x, n)

UVA 10869 - Brownie Points II(树阵)

UVA 10869 - Brownie Points II 题目链接 题意:平面上n个点,两个人,第一个人先选一条经过点的垂直x轴的线.然后还有一个人在这条线上穿过的点选一点作垂直该直线的线,然后划分出4个象限,第一个人得到分数为1.3象限,第二个人为二四象限.问第一个个人按最优取法,能得到最小分数的最大值,和这个值下还有一个人的得分可能情况 思路:树状数组,能够枚举一点,假设能求出右上和左下点的个数就好办了,其有用一个树状数组,把y坐标离散化掉,然后记录进来,然后把点按x从左往右,每次删掉点后

[UVA 12633] Super Rooks on Chessboard FFT+计数

如果只有行和列的覆盖,那么可以直接做,但现在有左上到右下的覆盖. 考虑对行和列的覆盖情况做一个卷积,然后就有了x+y的非覆盖格子数. 然后用骑士的左上到右下的覆盖特判掉那些x+y的格子就可以了. 注意题意,Row是从上到下来的,被坑得好惨. #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<ctim

UVA - 12633 Super Rooks on Chessboard FFT

题目链接:点这里 题意: 给你一个矩阵R*C,n个点,与给的的n个点同一列同一行,同一条主对角线上的点都被染黑 问你最后有多少个点没有被染黑 题解: 把每一列每一行没有被染黑的x,y找出来,其任意组合起来是没这种情况下的答案(同一条主对角线上的点都被染黑) 对于 x - y,我们可以拿来判断两个点是不是相同的一条主对角线上 那么对x.-y进行任意组合,FFT加速 总的答案就是,没有被染过行数*没有被染过的列数 - (找不到相同的x- y) 具体看代码吧 #include<bits/stdc++.

UVA 12633 Super Rooks on Chessboard (生成函数+FFT)

题面传送门 题目大意:给你一张网格,上面有很多骑士,每个骑士能横着竖着斜着攻击一条直线上的格子,求没被攻击的格子的数量总和 好神奇的卷积 假设骑士不能斜着攻击 那么答案就是没被攻击的 行数*列数 接下来考虑斜着攻击对答案的贡献 以左下角为坐标原点建立坐标系,发现一条对角线的点的$(x+y)$坐标是相同的 考虑卷积,设计两个生成函数$a,b$ 如果第i行没骑士,则$a_{i}=1$,反之为$0$ 如果第i列没骑士,则$b_{i}=1$,反之为$0$ 我们对两个式子进行卷积,可以求出每一条对角线上还

UVA 11426 GCD - Extreme (II) (数论|欧拉函数)

题意:求sum(gcd(i,j),1<=i<j<=n). 思路:首先可以看出可以递推求出ans[n],因为ans[n-1]+f(n),其中f(n)表示小于n的数与n的gcd之和 问题转化为了求f(n),因为小于n的数与n的gcd一定是n的因数, 所以f(n)可以表示为sum(i)*i,其中sum(i)表示所有和n的gcd为i的数的数量,我们要求满足gcd(a, n) = i,的个数,可以转化为求gcd(a/i, n/i) = 1的个数, 于是可以发现sun(i) = phi(n/i),这