• UVA


    题意:有四种花色的牌,每种花色的牌中只能使用数值的约数个数大于2的牌.现在遗失了c张牌.每种花色选一张,求值在区间[a,b]的每个数值的选择方法有多少.
    分析:约数个数大于2,即合数.所以先预处理出50000内的所有素数.
    然后根据给出的c个遗失牌和素数与否.构造生成多项式,因为上限是b,所以每个多项式只需构造b项即可.4类牌对应4个多项式,求三次卷积求出答案.

    坑点:复数类里要用long double

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int MAXN = 4e5 + 10;
    const long double PI = acos(-1.0);
    struct Complex{
        long double x, y;
        inline Complex operator+(const Complex b) const {
            return (Complex){x +b.x,y + b.y};
        }
        inline Complex operator-(const Complex b) const {
            return (Complex){x -b.x,y - b.y};
        }
        inline Complex operator*(const Complex b) const {
            return (Complex){x *b.x -y * b.y,x * b.y + y * b.x};
        }
    } va[MAXN * 2 + MAXN / 2], vb[MAXN * 2 + MAXN / 2];
    int lenth = 1, rev[MAXN * 2 + MAXN / 2];
    int N, M;   // f 和 g 的数量
        //f g和 的系数
        // 卷积结果
        // 大数乘积
    int f[MAXN],g[MAXN];
    vector<LL> conv;
    vector<LL> multi;
    //f g
    void init()
    {
        int tim = 0;
        lenth = 1;
        conv.clear(), multi.clear();
        memset(va, 0, sizeof va);
        memset(vb, 0, sizeof vb);
        while (lenth <= N + M - 2)
            lenth <<= 1, tim++;
        for (int i = 0; i < lenth; i++)
            rev[i] = (rev[i >> 1] >> 1) + ((i & 1) << (tim - 1));
    }
    void FFT(Complex *A, const int fla)
    {
        for (int i = 0; i < lenth; i++){
            if (i < rev[i]){
                swap(A[i], A[rev[i]]);
            }
        }
        for (int i = 1; i < lenth; i <<= 1){
            const Complex w = (Complex){cos(PI / i), fla * sin(PI / i)};
            for (int j = 0; j < lenth; j += (i << 1)){
                Complex K = (Complex){1, 0};
                for (int k = 0; k < i; k++, K = K * w){
                    const Complex x = A[j + k], y = K * A[j + k + i];
                    A[j + k] = x + y;
                    A[j + k + i] = x - y;
                }
            }
        }
    }
    void getConv(){             //求多项式
        init();
        for (int i = 0; i < N; i++)
            va[i].x = f[i];
        for (int i = 0; i < M; i++)
            vb[i].x = g[i];
        FFT(va, 1), FFT(vb, 1);
        for (int i = 0; i < lenth; i++)
            va[i] = va[i] * vb[i];
        FFT(va, -1);
        for (int i = 0; i <= N + M - 2; i++)
            conv.push_back((LL)(va[i].x / lenth + 0.5));
    }
    
    void getMulti()             //求A*B
    {
        getConv();
        multi = conv;
        reverse(multi.begin(), multi.end());
        multi.push_back(0);
        int sz = multi.size();
        for (int i = 0; i < sz - 1; i++){
            multi[i + 1] += multi[i] / 10;
            multi[i] %= 10;
        }
        while (!multi.back() && multi.size() > 1)
            multi.pop_back();
        reverse(multi.begin(), multi.end());
    }
    
    const int up = 500005;
    bool check[up];
    int cnt[up];
    
    void pre()
    {
        for(int i=2;i<up;++i){
            if(check[i]) continue;
            for(int j=2*i;j<up;j+=i){
                check[j] = true;
            }
        }
    }
    
    bool lack[4][up];
    char str[100];
    
    int main()
    {
        pre();
        int a,b,c;
        while(scanf("%d %d %d",&a, &b, &c)==3){
            if(!a && !b && !c) continue;
            memset(lack,0,sizeof(lack));
            for(int i=1;i<=c;++i){
                int tmp = 0; scanf("%d",&tmp);
                char c; scanf("%c",&c);
                if(c=='S') lack[0][tmp] = true;
                else if(c=='H') lack[1][tmp] = true;
                else if(c=='C') lack[2][tmp] = true;
                else lack[3][tmp] = true;
            }
            N = b;
            for(int i=0;i<b;++i){
                if(check[i] && !lack[0][i]) f[i] = 1;
                else f[i] =0;
            }
            for(int i=1;i<4;++i){
                if(i>1){
                    N = conv.size();
                    for(int j=0;j<N;++j){
                        f[j] = conv[j];
                    }
                }
                M = b;
                for(int j=1;j<b;++j){
                    if(check[j] && !lack[i][j])  g[j] = 1;
                    else g[j] = 0;
                }
                getConv();
            }
            for(int i=a;i<=b;++i){
                printf("%lld
    ",conv[i]);
            }
            puts("");
        }
        return 0;
    }
    
    为了更好的明天
  • 相关阅读:
    转游戏开发做的第一款手机网游的经历和体会
    cocos2d-x 单点事件用法
    cocos2d-x编译成android 以及android开发环境一些经验分享
    apk 反编译用法 mac上apktool
    cocos2d-x 中LUA和平台之间的函数调用理解
    项目经验
    sprintf 的基本用法
    html5标签 ----------- canvas vue / html
    vue 基于element组件库实现表格下多个子级展示
    vue基于proxy实现服务器反向代理功能
  • 原文地址:https://www.cnblogs.com/xiuwenli/p/9713180.html
Copyright © 2020-2023  润新知