2021牛客寒假算法基础集训营5 C.比武招亲(下)(拉格朗日插值法+欧拉降幂)

比武招亲(下)

https://ac.nowcoder.com/acm/problem/218514

集训营第二次考欧拉降幂了Orz
首先不管n,我们就算能选[1,m]的取值的时候的答案。和B题差不多的idea,我们能想到答案其实是,这是一个n+1次的多项式,如果说m很大的话,我们当然不能直接算,但是,我们可以利用拉格朗日插值法求出这个式的值。建议先学习下拉格朗日插值法。
之后,考虑的情况,我们当然不能直接算这个m,那么,题目给了模数,我们考虑只求m mod p的值,那么,考虑如何利用f(m mod p)求f(m).因为为n+1次多项式,那么,我们设,则,,二项式定理展开后,发现,因此,我们只需要求
对于,我们考虑欧拉降幂求即可。
这道题需要学的主要是欧拉降幂的写法,这里所用的EXP函数的方法,或者是官方题解中的预处理都是可以使用的方法,又或者是使用我第一场题解中的取对数的方法都是可行的。具体可以看下我的提交记录。

AC代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<typename T>
void read(T&x){
    x=0;
    char ch=getchar();
    int f=1;
    while(!isdigit(ch)){
        if(ch=='-')f*=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        x=x*10+(ch-'0');
        ch=getchar();
    }x*=f;
}
template<typename T>
void write(T x){
    if(x<0)putchar('-'),x=-x;
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
//===============================================================
#define int ll
#define MOD(x) (((x)%p+p)%p)
#define modit(a,b) ((a)>=(b)?(a)%(b)+(b):(a))
const int maxn=2e5+10;
int n,p;
int mul(int x,int y,int mod=::p){
    return 1ll*x*y%p;
}

int add(int x,int y,int mod=::p){
    return ((x+y)%p+p)%p;
}

ll ksm(ll a,ll n,ll p=::p){
    ll res=1;
    while(n){
        if(n&1)res=res*a%p;
        a=a*a%p;
        n>>=1;
    }
    return res;
}
unordered_map<int,int>mp;
int phi(int x){
    int bak=x;
    if(mp.count(bak))return mp[bak];
    int res=x;
    for(int i=2;i*i<=x;++i){
        if(x%i==0){
            res=res-res/i;
            while(x%i==0)x/=i;
        }
    }
    if(x>1)res=res-res/x;
    return mp[bak]=res;
}

int EXP(int a,int n,int p){
    int res=1;
    while(n){
        if(n&1)res=modit(res*a,p);
        a=modit(a*a,p);
        n>>=1;
    }
    return res;
}

int ex_euler(int n,int mod){
    if(mod==1)return 1;
    return ksm(n,ex_euler(n,phi(mod))+phi(mod),mod);
}
int f[maxn];
int fac[maxn],finv[maxn];
void init(int f[]){
    int lim=n+2;
    for(int i=1;i<=lim;++i){
        f[i]=MOD(f[i-1]+MOD(ksm(i,n+1)-i*ksm(i-1,n)));
    }
    fac[0]=1;
    for(int i=1;i<min(p,maxn);++i)fac[i]=mul(fac[i-1],i);
    finv[min(p-1,maxn-1)]=ksm(fac[min(p-1,maxn-1)],p-2,p);
    for(int i=min(p-2,maxn-2);i>=0;--i)finv[i]=mul(finv[i+1],(i+1));
}
int pre[maxn],suf[maxn];
ll solve(int y[],int n,int x){
    int lim=n+1;
    if(x<=lim)return y[x];
    pre[1]=1,suf[lim]=1;
    for(int i=2;i<=lim;++i)pre[i]=pre[i-1]*(x-(i-1))%p,pre[i]=(pre[i]%p+p)%p;
    for(int i=lim-1;i>=0;--i)suf[i]=suf[i+1]*(x-(i+1))%p,suf[i]=(suf[i]%p+p)%p;
    int res=0;
    for(int i=1;i<=lim;++i){
        int sig=((lim-i)&1?(-1):1);
        ll up=MOD(MOD(sig*suf[i]*pre[i])*f[i]);
        ll down=MOD(finv[i-1]*finv[lim-i]);
        res=(res+mul(up,down))%p;
        res=(res%p+p)%p;
        //res=add(res,MOD(sig*mul(mul(suf[i],pre[i]),mul(finv[i],finv[lim-i]))));
    }
    return res;
}

signed main(){
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    read(n),read(p);
    int m=ex_euler(n,p);
    init(f);
    int res=0;
    cout<<solve(f,n+1,m)<<endl;
    return 0;
}
全部评论

相关推荐

会员标识
02-20 16:28
已编辑
牛客运营
从03年的“北大毕业生卖猪肉”到前段时间上热搜的“北大博士入职城管”,这些年“下沉式就业”现象频繁牵动着大家的视野和目光吧,很吸睛?我觉得并不是,如果你说985大学生XXX,那可能成不了焦点,如果说是北大清华毕业生去当城管,卖猪肉,大家都会讨论一番,无论是谁都知道北大清华的过人之处。但是呢近些年的确有很多985、211名校毕业生选择到基层就业或回老家创业,会不会觉得大财小用?老家的哥哥,因为当时学的专业不是很好,但好在学校不错,一路本硕连读,毕业之后在上海打拼了2年,也攒了一些小钱,随后回村选择科学养鸡,买了很大一块地开始科学方法的养鸡、卖鸡蛋,村里的老人都会议论纷纷,白瞎了家里供你读书,又回...
下午吃泡馍:不是每一个脱下长衫的人在下沉市场重获新生,并不是每一个养猪养鸡的高学历人才都会成功。现实是很多人的“长衫”就是自己为数不多甚至唯一的底牌了,拼尽全力拿到一个不错的学历,这时候主流媒体告诉对方脱下长衫也可以活的精彩,其实真的挺难过的。强者恒强,但是弱者是人群的底色。 本质上是整个市场的问题,没有足够多的增长点,没有足够多的岗位,自上而下没有积极向上的氛围。外企撤出,供应链缺失...在发展的过程中总有阵痛,现阶段可能就是我们承受阵痛的过程。之前在牛客看到一个小伙伴说:时代的一粒灰尘,落在谁的身上,都将是无法承受之重!深有感触。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务