古代猪文

数论综合,考察代码能力(其实是脑子)……

首先分析一下其实就是求一个(1)。

略微转换一下(2)。

因为k是n的因子,n/k是n的因子,将两个因子交换位置就可以由(1)得到(2)。

接着就是尝试缩小计算规模的过程。

因为999911659是个素数,由欧拉定理的推论得:(3)。

那么我们就可以试着去求(4)。

尝试对999911658用唯一分解定理,发现可以拆成2,3,4679,35617。

这四个数是互质的,我们可以利用lucas定理将对2,3,4679,35617的余数分别求出,设为a1,a2,a3,a4。

问题转化为求一个x,使之满足:

这是一个典型的同余方程组,即:

x是可以用CRT求解的。

最后有了x,有了q,快速幂求一下q^x就是结果了。

下面的代码还是不要看的好,因为求fac和inv那一段特别丑,而且交完oj缩进问题十分严重。

有一个位置一开始打崩了,枚举因子时打成O(n)了,应该是O(sqrt(n))的,和判断素数那个思路差不多。

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<stack>
#define LL long long 
using namespace std;
LL n,q;
LL read(){
    LL sum=0;int f=1;char x=getchar();
    while(x<'0'||x>'9'){
        if(x=='-') f=-1;
        x=getchar();
    }while(x>='0'&&x<='9'){
        sum=sum*10+x-'0';
        x=getchar();
    }
    return sum*f;
    
}
LL p[6]={0,2,3,4679,35617};
LL fac[10][50050],inv[10][50050];
LL a[6];
LL qpow(LL x,LL k,LL mod){
    LL ans=1;
    for(;k;k>>=1,x=x*x%mod)
        if(k&1)
            ans=ans*x%mod;
    return ans;
}
void exgcd(LL a,LL b,LL &x,LL &y){
    if(!b){
        x=1;y=0;
        return;
    }
    exgcd(b,a%b,x,y);
    LL t=x;
    x=y;
    y=t-a/b*x;
    return ;
}
LL CRT(){
    LL ans=0,x,y;
    for(int i=1;i<=4;i++){
        exgcd(999911658/p[i],p[i],x,y);
        ans=(ans+a[i]*999911658/p[i]*x)%999911658;
    }return (ans+999911658)%999911658;
}
LL C(LL n,LL m,int i){
    if(m>n) return 0;
    return ((fac[i][n]*inv[i][m])%p[i])*inv[i][n-m]%p[i];
}
LL lucas(LL n,LL m,int i){
    if(m==0) return 1;
    return C(n%p[i],m%p[i],i)*lucas(n/p[i],m/p[i],i)%p[i];
}
void pre(){
    fac[1][0]=fac[2][0]=fac[3][0]=fac[4][0]=1;
    fac[1][1]=1;
    for(int i=1;i<=2;i++) fac[2][i]=fac[2][i-1]*i%p[2];
    for(int i=1;i<=4678;i++) fac[3][i]=fac[3][i-1]*i%p[3];
    for(int i=1;i<=35616;i++) fac[4][i]=fac[4][i-1]*i%p[4];
    inv[1][1]=qpow(fac[1][1],p[1]-2,p[1]);
    inv[2][2]=qpow(fac[2][2],p[2]-2,p[2]);
    inv[3][4678]=qpow(fac[3][4678],p[3]-2,p[3]);
    inv[4][35616]=qpow(fac[4][35616],p[4]-2,p[4]);
    for(int i=35616;i>=1;i--)
        inv[4][i-1]=inv[4][i]*i%p[4];
    for(int i=4678;i>=1;i--)
        inv[3][i-1]=inv[3][i]*i%p[3];
    for(int i=2;i>=1;i--)
        inv[2][i-1]=inv[2][i]*i%p[2];
    for(int i=1;i>=1;i--)
        inv[1][i-1]=inv[1][i]*i%p[1];

}
int main(){
    n=read();q=read();
    if(q%999911659==0){
        puts("0");
        return 0;
    }
    pre();
    for(int i=1;i*i<=n;i++){
        if(n%i==0){
            for(int j=1;j<=4;j++)
                a[j]=(a[j]+lucas(n,i,j))%p[j];
            if(i*i!=n)
                for(int j=1;j<=4;j++)
                    a[j]=(a[j]+lucas(n,n/i,j)%p[j]);
        }
    }
    LL o=CRT();
    printf("%lld
",qpow(q,o,999911659));
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/Yu-shi/p/11096222.html