zoukankan      html  css  js  c++  java
  • exlucas易错点

    模板和题解

    复习了一下 exlucas的模板,结果写挂四次(都没脸说自己以前写过

    是该好好反思一下呢~

    错的原因如下:

    第一次WA:求阶乘的时候忘了递归处理(n/p)!

    第二次WA:求阶乘时把p当成循环节了,循环节应该是(p^k)

    第三次WA:把循环节改成(p^k)后,干脆把递归处理(n/p)!改成了递归处理(n/(p^k))! (智障

    第四次WA:求(p^k)的逆元直接用(p^k)^(mod-2),然而(p^k)不一定是质数,不能用费马小定理,应该用exgcd求逆元

    就因为这几个错误花了我两个小时的时间,其实主要原因是自己没想清楚,连exlucas式子都推错,看题解也太心急了没认真看,导致自己反复错。

    还有就是自己数论的基础太差,比如第四次错误就想当然以为(p^k)的逆元是它的(mod-2)次方,连费马小定理的条件都忘了

    (PS:好像luogu上此题开O2会全T?相同的代码不开O2都过了)

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 107
     4 #define ll long long
     5 ll p2(ll x,ll mod)
     6 {
     7     return x*x%mod;
     8 }
     9 ll pw(ll x,ll p,ll mod)
    10 {
    11     return p?p2(pw(x,p/2,mod),mod)*(p&1?x:1)%mod:1;
    12 }
    13 ll fun(ll n,ll p)
    14 {
    15     if(n<p)return 0;
    16     return fun(n/p,p)+n/p;
    17 }
    18 ll exfac(ll n,ll p,ll mod)
    19 {
    20     if(n==0)return 1;
    21     ll i,mul=1;
    22     for(i=1;i<=mod;i++)
    23         if(i%p!=0)mul=mul*i%mod;
    24     ll ans=pw(mul,n/mod,mod);
    25     ll rest=n%mod;
    26     for(i=1;i<=rest;i++)
    27         if(i%p!=0)ans=ans*i%mod;
    28     return ans*exfac(n/p,p,mod)%mod;
    29 }
    30 ll exgcd(ll x,ll y,ll &a,ll &b)
    31 {
    32     ll z;
    33     return y?(z=exgcd(y,x%y,b,a),b-=a*(x/y),z):(a=1,b=0,x);
    34 }
    35 ll getinv(ll a,ll p)
    36 {
    37     ll x,y;
    38     exgcd(a,p,x,y);
    39     x=(x%p+p)%p;
    40 }
    41 ll exlucas(ll n,ll m,ll p,ll mod)
    42 {
    43     ll ans=exfac(n,p,mod);
    44     ans=ans*getinv(exfac(m,p,mod),mod)%mod;
    45     ans=ans*getinv(exfac(n-m,p,mod),mod)%mod;
    46     ll times=fun(n,p)-fun(m,p)-fun(n-m,p);
    47     ans=ans*pw(p,times,mod)%mod;
    48     return ans;
    49 }
    50 ll a[N],b[N],cnt;
    51 void getans(ll n,ll m,ll p)
    52 {
    53     ll t=sqrt(p),i,x=p;
    54     for(i=2;i<=p;i++)
    55     {
    56         if(x%i==0)
    57         {
    58             ll mod=1;
    59             while(x%i==0)x/=i,mod*=i;
    60             ll res=exlucas(n,m,i,mod);
    61             //printf("%lld
    ",res);
    62             a[++cnt]=res,b[cnt]=mod;
    63         }
    64     }
    65 }
    66 int main()
    67 {
    68     ll n,m,p,i;
    69     scanf("%lld%lld%lld",&n,&m,&p);
    70     getans(n,m,p);
    71     ll ans=0;
    72     for(i=1;i<=cnt;i++)
    73     {
    74         ll M=p/b[i];
    75         ll x=a[i]*M%p*getinv(M,b[i])%p;
    76         ans=(ans+x)%p;
    77     }
    78     printf("%lld
    ",ans);
    79     return 0;
    80 }
  • 相关阅读:
    Java 读取大容量excel
    Linux 安装mysql
    Linux 配置nginx
    java 微信H5支付
    微信公众号授权登录两种方式
    Jsoup 获取页面返回的table中的内容
    Python Model执行迁移数据库失败
    java上传txt文件,出现中文乱码
    在Window环境下,使用Django shell 命令查询数据库
    Java模拟form表单提交普通参数和文件
  • 原文地址:https://www.cnblogs.com/lishuyu2003/p/11185586.html
Copyright © 2011-2022 走看看