• bzoj 2655: calc


    2655: calc

    Time Limit: 30 Sec  Memory Limit: 512 MB
    Submit: 339  Solved: 206
    [Submit][Status][Discuss]

    Description


      一个序列a1,...,an是合法的,当且仅当:
      长度为给定的n。
      a1,...,an都是[1,A]中的整数。
      a1,...,an互不相等。
      一个序列的值定义为它里面所有数的乘积,即a1a2...an。
      求所有不同合法序列的值的和。
      两个序列不同当且仅当他们任意一位不一样。
      输出答案对一个数mod取余的结果。

    Input

      一行3个数,A,n,mod。意义为上面所说的。

    Output

      一行结果。

    Sample Input

    9 7 10007


    Sample Output

    3611

    HINT

    数据规模和约定

      0:A<=10,n<=10。

      1..3:A<=1000,n<=20.

      4..9:A<=10^9,n<=20

      10..19:A<=10^9,n<=500。

      全部:mod<=10^9,并且mod为素数,mod>A>n+1

    发现可以用容斥乱搞,设f[i]为已经选了i个数的互不相等的权值和,S(n,k)为1-n的k次前缀和。

    那么 f[i]=∑ f(i-j-1) * S(A,j+1) * (-1)^j * P(i-1,j)       ,其中0<=j<i

    相当于把下一个选的数作为基准,+一个都不同的权值和-有一个和下一个相同的权值和+有两个和下一个相同的权值和.....

    接下来就是求S(n,k)了,这个玩意好像叫伯努利数,但并不是很难推。

    显然的是:(n+1)^k-n^k = C(k,1)*n^(k-1) +C(k,2)*n^(k-2)+....+C(k,k)*n^0

    把n从1带到n,等号左边和右边都加起来:

    (n+1)^k-1=C(k,1)*S(n,k-1)+C(k,2)*S(n,k-2)+....+C(k,k)*S(n,0)

    移项之后就可以通过S(n,k-1),S(n,k-2).....S(n,0)来求S(n,k)了  (需要求一下逆元)

    (然而好像还有复杂度线性的求法???脑子炸了回来再学吧hhhh)

    (不过跑的还蛮快的)

    /**************************************************************
        Problem: 2655
        User: JYYHH
        Language: C++
        Result: Accepted
        Time:204 ms
        Memory:3300 kb
    ****************************************************************/
     
    #include<bits/stdc++.h>
    #define ll long long
    #define maxn 505
    using namespace std;
    ll ni[maxn],n,A,p;
    ll C[maxn][maxn],jc[maxn];
    ll S[maxn],f[maxn];
     
    inline void init(const ll ha){
        jc[0]=C[0][0]=1;
        for(int i=1;i<=n+1;i++){
            jc[i]=jc[i-1]*(ll)i%ha;
            C[i][0]=1;
            for(int j=1;j<=i;j++){
                C[i][j]=C[i-1][j-1]+C[i-1][j];
                if(C[i][j]>=ha) C[i][j]-=ha;
            }
        }
         
        ni[1]=1;
        for(int i=2;i<=n+1;i++) ni[i]=-ni[ha%i]*(ha/i)%ha+ha;
         
        S[0]=A; 
        ll now=(A+1)%ha,cnt;
        for(int i=1;i<=n;i++){
            now=now*(A+1)%ha;
            S[i]=1-now+ha;
            for(int j=i-1;j>=0;j--){
                S[i]+=C[i+1][i-j+1]*S[j];
                if(S[i]>=ha) S[i]-=S[i]/ha*ha;
            }
            S[i]=-S[i];
            if(S[i]<0) S[i]+=ha;
            S[i]=S[i]*ni[i+1]%ha;
        }
         
    //  for(int i=0;i<=n;i++) cout<<S[i]<<endl;
    }
     
    inline void dp(const ll ha){
        f[0]=1; ll now,val;
        for(int i=1;i<=n;i++)
            for(int j=0,p=1;j<i;j++,p*=-1){
                val=f[i-j-1]*S[j+1];
                if(val>=ha) val-=val/ha*ha;
                val*=p;
                if(val<0) val+=ha;
                 
                now=C[i-1][j]*jc[j];
                if(now>=ha) now-=now/ha*ha;
                 
                f[i]+=now*val;
                if(f[i]>=ha) f[i]-=f[i]/ha*ha;
            }
    }
     
    int main(){
        scanf("%lld%lld%lld",&A,&n,&p);
        const ll ha=p;
        init(ha);
        dp(ha);
        printf("%lld
    ",f[n]);
        return 0;
    }
  • 相关阅读:
    项目外部 property文件使用方法
    java JsonArray统一添加key
    java发送Http请求
    excel数据追加,java实现
    request.getParameter("name")获取参数为null和""空字符串的区别
    maven 配置jetty插件启动 及简单测试
    左右值编码实现树状存储
    Spring将classpath下的 .properties文件数据读出放到map中,在初始化时加载
    Ubuntu简单配置
    java.io.Serializable浅析
  • 原文地址:https://www.cnblogs.com/JYYHH/p/8315594.html
Copyright © 2020-2023  润新知