zoukankan      html  css  js  c++  java
  • 洛谷3321 SDOI2015 序列统计

    懒得放传送【大雾

    有趣的一道题

    前几天刚好听到Creed_神犇讲到相乘转原根变成卷积的形式

    看到这道题当然就会做了啊w

    对于m很小 我们暴力找原根 如果你不会找原根的话 出门左转百度qwq

    找到原根以后所有数转成原根的幂次然后卷积就吼了啊

    多项式卡速米 由于是循环卷积所以每一次还要转回系数相加再转回来

    所以是不优美的O(nlg^2n) =v=

    代码在这里。

    //Love and Freedom.
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define inf 20021225
    #define ll long long
    #define wph 1004535809ll
    #define mxn 810000
    using namespace std;
    
    int ksm(int bs,int mi,int mdn)
    {
        int ans=1;
        while(mi)
        {
            if(mi&1)	ans=(ll)ans*bs%mdn;
            bs=(ll)bs*bs%mdn; mi>>=1;
        }
        return ans;
    }
    
    int n,m,x,s;
    int G,rev[mxn<<1];
    int id[mxn];
    void find_G()
    {
        for(int i=2;i<=m;i++)
        {
            memset(id,0,sizeof(id));
            int tmp=1,j;
            for(j=0;j<m-1;j++)
            {
                if(id[tmp])	break;
                id[tmp] = j;
                tmp*=i; tmp%=m;
            }
            if(j==m-1){G=i;return;}
        }
    }
    
    void NTT(int *a,int n,int f)
    {
        for(int i=0;i<n;i++)	if(rev[i]>i)
            swap(a[rev[i]],a[i]);
        for(int k=2,mid=1;k<=n;k<<=1,mid<<=1)
        {
            int Wn=ksm(3,(wph-1)/k,wph);
            if(f)	Wn=ksm(Wn,wph-2,wph);
            for(int i=0,w=1;i<n;i+=k,w=1)
            for(int j=0;j<mid;j++,w=(ll)w*Wn%wph)
            {
                int x=a[i+j],y=(ll)w*a[i+mid+j]%wph;
                a[i+j]=(x+y)%wph; a[i+mid+j]=(x-y+wph)%wph;
            }
        }
        if(f)	for(int i=0,inv=ksm(n,wph-2,wph);i<n;i++)
            a[i] = (ll)a[i]*inv%wph;
    }
    
    int init(int n)
    {
        int lim=1,l=0;
        while(lim<n)	lim<<=1,l++;
        for(int i=0;i<lim;i++)
            rev[i] = (rev[i>>1]>>1)|((i&1)<<(l-1));
        return lim;
    }
    
    void poly_ksm(int *ans,int *bs,int n,int mi)
    {
        //for(int i=0;i<n;i++)	printf("%d ",bs[i]);
        //printf("
    ");
        ans[0] = 1;
        int lim = init(n<<1);
        NTT(ans,lim,0); NTT(bs,lim,0);
        //printf("%d
    ",ans[0]);
        while(mi)
        {
            if(mi&1)
            {
                //printf("%d
    ",n);
                for(int i=0;i<lim;i++)
                    ans[i] =(ll)ans[i]*bs[i]%wph;
                NTT(ans,lim,1);
                //ans[0] = 0;
                for(int i=0;i<n-1;i++)
                    ans[i] = (ans[i]+ans[i+n-1])%wph,ans[i+n-1]=0;
                NTT(ans,lim,0);
            }
            for(int i=0;i<lim;i++)	bs[i]=(ll)bs[i]*bs[i]%wph;
            NTT(bs,lim,1);
            //bs[0] = 0;
            for(int i=0;i<n-1;i++)	bs[i]=(bs[i]+bs[i+n-1])%wph,bs[i+n-1]=0;
            NTT(bs,lim,0);
            mi>>=1;
        }
        NTT(ans,lim,1);
        //for(int i=0;i<lim;i++)	printf("%d ",ans[i]);
    }
    
    int a[mxn<<1],ans[mxn<<1];
    int main()
    {
        scanf("%d%d%d%d",&n,&m,&x,&s);
        find_G();int t;
        for(int i=1;i<=s;i++)
        {
            scanf("%d",&t);
            if(t%m==0)	continue;
            t%=m;	a[id[t]]++;
        }
        poly_ksm(ans,a,m,n);
        printf("%d
    ",ans[id[x]]);
        return 0;
    }
  • 相关阅读:
    windows服务启动有界面的程序
    [转发]读取txt防止读到乱码--自动根据文件编码进行读取
    线程UI同步
    SQL2012导出的脚本没有if exists判断
    power designer 设计数据库生成到oracle数据库
    经典三层,单元工作模式出错的解决方案
    EF ObjectStateManager 中已存在具有同一键的对象。ObjectStateManager 无法跟踪具有相同键的多个对象
    Oracle 11g 客户端连接 oracle 10g 服务端,乱码问题
    EF 连接oracle 基础连接失败 问题解决
    vs2010 oraclelient 引用问题
  • 原文地址:https://www.cnblogs.com/hanyuweining/p/10321885.html
Copyright © 2011-2022 走看看