zoukankan      html  css  js  c++  java
  • 【spoj SEQN】【hdu 3439】Sequence

    题意:

    给出n、m、k 求C(n,k)*H(n-k)%m的值 H(n-k)为错排公式

    题解:

    先算H(n-k)

    计算H(n)有个通式:

    H(n)=(-1)^n+((-1)^(n-1))n+((-1)^(n-2))n(n-1)+...+n(n-1)(n-2)...3

    证明详见维基百科:

    http://zh.wikipedia.org/wiki/%E9%94%99%E6%8E%92%E9%97%AE%E9%A2%98#.E7.AE.80.E5.8C.96.E5.85.AC.E5.BC.8F

    因为我们是要算H(n-k)mod m的值 显然他的前不超过m项是>0的 而其它都为0 枚举求解即可

    _________________________________________________________________________________

    再说C(n,k)%m

    我们知道世界上有个叫 Lucas 定理的东西:

    C(n, m) % p = C(n / p, m / p) * C(n % p, m % p) % p

    但是它要求p是质数 所以它和本题的正解没什么关系- -

    _________________________________________________________________________________

    由于除的数可能不与m互质 所以不能用乘法逆元

    不妨将m分解 m=p1^a1*p2^a2*...*pn^an

    分别计算C(n,k)%(pi^ai) 的值 最后用中国剩余定理计算答案

    于是问题转换为求C(n,k)%(p^a)的值

    C(n,k)=n!/((n-k)!*k!)

    为了让乘法逆元能能使用 只要将n!、(n-k)!、k! 所有p的倍数 提出来单独计算即可

    如果n比较小 枚举计算不为p的倍数的数的积即可 但是这里n<=10^9 我们就需要用一些比较高端的方法

    设A(n)=(1*2*..*(p-1)*(p+1)*...*(2p-1)*(2p+1)*...*n)

    n!=A(n)*(p*2p*...*(n/p)p)

       =A(n)*(n/p)!*p^(n/p)

       =A(n)*A(n/p)*(n/p/p)!*p^(n/p/p)*p^(n/p)

       =...

    就是对n!不断的分解为A(n)*(n/p)!*p^(n/p) 再递归处理(n/p)! 直到n/p为0

    当然在计算的同时 要累加/减 p的指数sum

    这样就能求出C(n,k)不包含p的乘积了 最后再乘p^sum 即为C(n,k)%(p^a)

    _________________________________________________________________________________

    问题结束了吗- - 显然木有 对于A(n)还需要用O(n)的时间求出 TLE!

    设r=p^a

    这里A(n)的值是要模r的 我们可以这样转换

    A(n)=1*2*..*(p-1)*(p+1)*...*(2p-1)*(2p+1)*...*n

          =(1*2*...*(r-1))*((r+1)*(r+2)*...*(2r-1))*(...*n)

          =(1*2*...*(r-1))*(1*2*...*(r-1))*...*(1*2*...*n%r) (mod r)

    我们就可以预处理save[i]存下1*2*...*i (p的倍数不乘,i<=r-1)

    A(n)=save[r-1]^(n/r)*save[n%r] 快速幂就可用log(n)的时间求出A

    加上预处理O(r) r<=m<=10^5

    最后乘m的质因数的个数blabla- -具体多少我也不知道了 反正能过

    _________________________________________________________________________________

    代码:

     1 #include <cstdio>
     2 typedef long long ll;
     3 const ll M=100001;
     4 ll n,k,m,t,a[M],r[M],ans,p[M],pri[M],bo[M],zs[M],save[M],tot;
     5 void makepri(){
     6     for (ll i=2;i<M;i++){
     7         if (!bo[i]) pri[++pri[0]]=i;
     8         for (ll j=1;j<=pri[0] && i*pri[j]<M;j++){
     9             bo[i*pri[j]]=1;
    10             if (!(i%pri[j])) break;
    11         }
    12     }
    13 }
    14 ll mi(ll a,ll b,ll mo){
    15     ll res=1%mo;
    16     for (;b;b>>=1){
    17         if (b&1) res=res*a%mo;
    18         a=a*a%mo;
    19     }
    20     return res;
    21 }
    22 ll extgcd(ll &x,ll &y,ll a,ll b){
    23     if (!b){
    24         x=1,y=0;
    25         return a;
    26     }else{
    27         ll res=extgcd(x,y,b,a%b);
    28         ll t=x;
    29         x=y;
    30         y=t-a/b*y;
    31         return res;
    32     }
    33 }
    34 ll getny(ll a,ll b){
    35     ll x,y,gc=extgcd(x,y,a,b),mo=b/gc;
    36     x=(x%mo+mo)%mo;
    37     return x;
    38 }
    39 
    40 void makep(){
    41     p[0]=r[0]=0;
    42     for (ll i=1,x=m;i<=pri[0] && x>1;i++)
    43     if (!(x%pri[i])){
    44         p[++p[0]]=pri[i];
    45         r[++r[0]]=1;
    46         while (!(x%pri[i])) x/=pri[i],r[r[0]]*=pri[i];
    47     }
    48 }
    49 void makesave(ll t){
    50     save[0]=1;
    51     for (ll i=1,x=1;i<=r[t];i++){
    52         if (i%p[t]) x=x*i%r[t];
    53         save[i]=x;
    54     }
    55 }
    56 ll jc(ll n,ll t,ll &z,ll bo){
    57     if (!n) return 1;
    58     z+=bo*(n/p[t]);
    59     return mi(save[r[t]],n/r[t],r[t])*save[n%r[t]]%r[t]*jc(n/p[t],t,z,bo)%r[t];
    60 }
    61 ll getc(){
    62     makep();
    63     for (ll i=1;i<=p[0];i++){
    64         zs[i]=0;
    65         makesave(i);
    66         a[i]=jc(n,i,zs[i],1)*getny(jc(n-k,i,zs[i],-1)*jc(k,i,zs[i],-1)%r[i],r[i])%r[i];
    67         a[i]=a[i]*mi(p[i],zs[i],r[i])%r[i];
    68     }
    69     ll res=0;
    70     for (ll i=1;i<=p[0];i++)
    71     res=(res+m/r[i]*getny(m/r[i],r[i])%m*a[i]%m)%m;
    72     return res;
    73 }
    74 
    75 ll geth(ll n){
    76     if (n==1) return 0;
    77     ll res=(n&1) ? -1 : 1;
    78     for (ll i=n,x=n*res*-1%m;i>=3 && x;x=x*(--i)*-1%m)
    79     res=((res+x)%m+m)%m;
    80     return res;
    81 }
    82 
    83 int main(){
    84     scanf("%I64d",&t);
    85     makepri();
    86     for (ll i=1;i<=t;i++){
    87         tot=i;
    88         scanf("%I64d%I64d%I64d",&n,&k,&m);
    89         ans=(getc()*geth(n-k)%m+m)%m;
    90         printf("Case %I64d: %I64d
    ",i,ans);
    91     }
    92 }
    View Code

    注:这个代码能过hdu的数据但是不能过spoj的... 可能有点小bug- -?(我说spoj → →)

  • 相关阅读:
    整数m去掉n位后剩下最大(小)值
    蛇形矩阵(二)
    Kibana源码启动报错记录--ENOSPC
    Kibana问题记录:yarn test 运行报错 error Trailing spaces not allowed no-trailing-spaces
    Vim 编辑器中全选操作
    Ubuntu系统中连接TFS的Git地址注意事项
    Ubuntu系统升级遇到问题记录
    Kibana6.2.x 插件理解
    Kibana问题搜集---下载源码,执行npm install 报错
    Kibana6.2.2源码入口
  • 原文地址:https://www.cnblogs.com/g-word/p/3381360.html
Copyright © 2011-2022 走看看