zoukankan      html  css  js  c++  java
  • bzoj 1951 [Sdoi2010]古代猪文(数论知识)

    【题目链接】

      http://www.lydsy.com/JudgeOnline/problem.php?id=1951

    【思路】

           一道优(e)秀(xin)的数论题。

           首先我们要求的是(G^sigma{ C(n,n/i),i|n })%P,即G^M %P,根据费马小定理G^(P-1) ≡1(mod P),我们要求的就是G^(M%(P-1)) %P。

           考虑C(n,i)%(P-1),由于n i P都比较大所以不好求组合数。发现P-1可以分解质因数为2,3,4679,35617,将C(n,i)对每一个质因子取模,会得到一个形为x≡ ai(mod pi)的模线性方程组,可以用中国剩余定理确定x。对于C(n,i)%p,此时p比较小,我们可以用lucas定理求解。

           总的来说就是先用O(sqrt(n))的时间枚举约数,然后用lucas定理求出不同模数下的ai,最后联立方程组,中国剩余定理解。

           注意当(G,P)!=1的时候费马小定理不成立,此时答案为0。

           关于lucas的写法,a^p-2 %p是a在模p下的逆,因为a^(p-2) *a=a^(p-1),由费马小定理得a^(p-1) %p=1,因此p必须满足为质数才能使用这种方法。

    【定理】

    1—  欧拉定理

    当a与p互质时,a^phi(p) mod p=1 

    费马小定理即欧拉定理在p为质数时的特例, a(p-1)  ≡1 mod p

    2—  Lucas定理

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

    【代码】

     1 #include<cmath>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<iostream>
     5 using namespace std; 
     6 
     7 typedef long long LL;
     8 const int N = 36000;
     9 const LL mod[5]={2,3,4679,35617,999911659}; 
    10 
    11 LL fac[4][N],a[4],n,G;
    12 
    13 void gcd(LL a,LL b,LL &x,LL& y) {
    14     if(!b) { x=1;y=0; }
    15     else gcd(b,a%b,y,x) , y-=x*(a/b);
    16 }
    17 LL pow(LL x,LL p,LL MOD) {
    18     LL ans=1;
    19     while(p) {
    20         if(p&1) ans=(ans*x)%MOD;
    21         x=(x*x)%MOD; p>>=1;
    22     }
    23     return ans;
    24 }
    25 LL C(LL n,LL m,int x) {
    26     if(n<m) return 0;
    27     return (fac[x][n]*pow(fac[x][n-m]*fac[x][m],mod[x]-2,mod[x]))%mod[x];
    28 }
    29 LL lucas(LL n,LL m,int x) {
    30     if(!m) return 1;
    31     return lucas(n/mod[x],m/mod[x],x)*C(n%mod[x],m%mod[x],x)%mod[x];
    32 }
    33 LL china() {
    34     LL M=1,d,x,y,ans=0;
    35     for(int i=0;i<4;i++) M*=mod[i];
    36     for(int i=0;i<4;i++) {
    37         d=M/mod[i];
    38         gcd(d,mod[i],x,y);
    39         ans=(ans+d*x*a[i])%M;
    40     }
    41     while(ans<=0) ans+=M;
    42     ans=(ans+M)%M;
    43     return ans;
    44 }
    45 void get_fac() {
    46     for(int i=0;i<4;i++) {
    47         fac[i][0]=1;
    48         for(int j=1;j<=mod[i];j++)
    49             fac[i][j]=(fac[i][j-1]*j)%mod[i];
    50     }
    51 }
    52 int main() {
    53     get_fac();
    54     scanf("%lld%lld",&n,&G);
    55     G%=mod[4];
    56     if(!G) { puts("0"); return 0; }
    57     for(int i=1;i*i<=n;i++) if(n%i==0) {
    58         LL tmp=n/i;
    59         for(int j=0;j<4;j++) {
    60             a[j]=(a[j]+lucas(n,tmp,j))%mod[j];
    61             if(tmp!=i) a[j]=(a[j]+lucas(n,i,j))%mod[j];
    62         }
    63     }
    64     printf("%lld",pow(G,china(),mod[4]));
    65     
    66     return 0;
    67 }
  • 相关阅读:
    网络安全部门的漏洞扫描让你头痛不已么——PHP环境选它就可以了
    2009年系统架构设计师考试试题知识点整理(一)
    解决EasyUI DataGrid删除行失败的方法
    贝叶斯文本分类原理
    为什么要对博客进行机器自动分类
    《机器学习实战》 in python3.x
    网站分析数据收集方式详解
    ThinkPHP5项目目录规划实践
    NumPy基础:用于数组的文件输入输出
    NumPy基础:通用函数-快速的元素级数组函数
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5223344.html
Copyright © 2011-2022 走看看