zoukankan      html  css  js  c++  java
  • 数学(快速数论变换):SDOI2015 序列统计

    【题目描述】

    小C有一个集合S,里面的元素都是小于M的非负整数。他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S。

    小C用这个生成器生成了许多这样的数列。但是小C有一个问题需要你的帮助:给定整数x,求所有可以生成出的,且满足数列中所有数的乘积mod M的值等于x的不同的数列的有多少个。小C认为,两个数列{Ai}和{Bi}不同,当且仅当至少存在一个整数i,满足Ai≠Bi。另外,小C认为这个问题 的答案可能很大,因此他只需要你帮助他求出答案mod 1004535809的值就可以了。

    【输入格式】

    一行,四个整数,N、M、x、|S|,其中|S|为集合S中元素个数。

    第二行,|S|个整数,表示集合S中的所有元素。

    【输出格式】

    一行,一个整数,表示你求出的权值和mod 1004535809的值。

    【样例输入】

    4 3 1 2

    1 2

    【样例输出】

    8

    【提示】

    对于10%的数据,1<=N<=1000;

    对于30%的数据,3<=M<=100;

    对于60%的数据,3<=M<=800;

    对于全部的数据,1<=N<=10^9,3<=M<=8000,M为质数,0<=x<=M-1,输入数据保证集合S中元素不重复。

      竟然没有x=0的数据。

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 using namespace std;
     5 const int N=32768,G=3;
     6 const int MOD=1004535809;
     7 int g,n,m,x,s,pos[N],num[N];
     8 int Qpow(int x,int k,int mod){
     9     long long ret=1;
    10     while(k){
    11         if(k&1)ret=1ll*ret*x%mod;
    12         x=1ll*x*x%mod;k>>=1;
    13     }
    14     return ret;
    15 }
    16 
    17 void Rader(int *a,int len){
    18     for(int i=1,j=len>>1;i<len-1;i++){
    19         if(i<j)swap(a[i],a[j]);
    20         int k=len>>1;
    21         while(j>=k){
    22             j-=k;
    23             k>>=1;
    24         }
    25         j+=k;
    26     }
    27 }
    28 
    29 void NTT(int *a,int len,int on){
    30     Rader(a,len);
    31     for(int h=2,wn;h<=len;h<<=1){
    32         if(on==1)wn=Qpow(G,(MOD-1)/h,MOD);
    33         else wn=Qpow(G,MOD-1-(MOD-1)/h,MOD);
    34         for(int j=0;j<len;j+=h){
    35             int w=1,x,y;
    36             for(int k=j;k<j+(h>>1);k++){
    37                 x=a[k];y=1ll*a[k+(h>>1)]*w%MOD;
    38                 a[k]=(x+y)%MOD;a[k+(h>>1)]=(x-y+MOD)%MOD;
    39                 w=1ll*w*wn%MOD;
    40             }
    41         }
    42     }
    43     if(on==-1){
    44         int inv=Qpow(len,MOD-2,MOD);
    45         for(int i=0;i<len;i++)
    46             a[i]=1ll*a[i]*inv%MOD;
    47     }    
    48 }
    49 
    50 int f[N],r[N],l=N/2;
    51 void Solve(){
    52     for(int i=0;i<N;i++)
    53         r[i]=f[i];n-=1;
    54     while(n){
    55         NTT(f,N,1);
    56         if(n&1){
    57             NTT(r,N,1);
    58             for(int i=0;i<N;i++)r[i]=1ll*r[i]*f[i]%MOD;
    59             NTT(r,N,-1);
    60             for(int i=m-1;i<N;i++)(r[i%(m-1)]+=r[i])%=MOD,r[i]=0;
    61         }
    62         for(int i=0;i<N;i++)f[i]=1ll*f[i]*f[i]%MOD;
    63         NTT(f,N,-1);
    64         for(int i=m-1;i<N;i++)(f[i%(m-1)]+=f[i])%=MOD,f[i]=0;
    65         n>>=1;
    66     }
    67     printf("%d
    ",r[pos[x]]);
    68 }
    69 
    70 void Solve_Zero(){int cnt=0,ans;
    71     for(int i=1;i<=s;i++)if(!num[i])cnt++;
    72     ans=Qpow(s,n,MOD)-Qpow(s-cnt,n,MOD);
    73     printf("%d
    ",ans);
    74 }
    75 int main(){
    76     freopen("sdoi2015_sequence.in","r",stdin);
    77     freopen("sdoi2015_sequence.out","w",stdout);
    78     scanf("%d%d%d%d",&n,&m,&x,&s);
    79     for(int i=1;i<=s;i++)
    80         scanf("%d",&num[i]);
    81     if(!x)Solve_Zero();
    82     for(g=1;g<m;g++){int i;
    83         for(i=1;i<m-1;i++)
    84             if(Qpow(g,i,m)==1)
    85                 break;
    86         if(i==m-1&&Qpow(g,m-1,m)==1)break;        
    87     }
    88     for(int i=1;i<m;i++)
    89         pos[Qpow(g,i,m)]=i%(m-1);
    90     for(int i=1;i<=s;i++)
    91         if(num[i])f[pos[num[i]]]++;
    92     Solve();
    93     return 0;
    94 }
  • 相关阅读:
    springboot 集成RabbitMQ
    服务接口API限流 Rate Limit 续
    服务接口API限流 Rate Limit
    聊下并发和Tomcat线程数
    java 线程池 异步任务
    Tomcat中更改网站根目录和默认页的配置方法
    QPS从0到4000请求每秒,谈达达后台架构演化之路
    分布式与集群是什么 ? 区别是什么?
    大型网站技术架构演变总结
    提升高并发量服务器性能解决思路
  • 原文地址:https://www.cnblogs.com/TenderRun/p/5795402.html
Copyright © 2011-2022 走看看