Wannafly 模拟赛5 E 思维+数论

来源:互联网 发布:阿里云数据库实时备份 编辑:程序博客网 时间:2024/05/21 22:47

题目链接


参考博客(感谢)

用自己的语言简单总结一下…..加深理解。

题意:
Aria正面临算设课程的考试。

F(n)=i=1nj=1ij=i=1ni!

对于给定的n,m(其中n为质数),求F(nm)中质因子n的出现次数,即求一个最大的非负整数e满足ne整除F(nm)。
由于是算设课的考试,答案当然是对109+7取模的。

思路:
首先此题需要基于一个重要的数论知识点:
对于一个数n,所包含的某个因子m的次数是:

int calc(int n,int m){    int ans = 0;    while(n){        ans += n/m;        n = n/m;    }    return ans;}

证明:
k=n/m
因为:
n!=123...n
试着将因子m提出,则一定有:(C为一个不含因子m的数)
n!=(m(2m)(3m)...(km))C
    =k!mkC

所以k一定是最后所求个数的一部分。
另一部分则是k!中所包含因子m的个数。递归处理即可。
证毕。


calc(n,m)n!中所含因子m的个数。
因为n为质数,则只需要单独考虑1nm中每个数所含因子n个数的和。

ans=i=1nmcalc(i,n)

由上面的证明的数论知识,我们易得:
对于i[kn,kn+n1]calc(i,n)相同
故我们考虑将1nm中的所有数每n个分为一组,则一组中所有数对答案的贡献相同。
对于nm则需要特殊考虑,故答案可以化简为:

ans=calc(nm,n)+i=1nm1calc(i,n)

=i=0m1ni+ni=1nm11calc(in,n)

因为:calc(in,n)=i+calc(i,n)
所以:

ans=nm1n1+n(i=1nm11i+i=1nm11calc(i,n))

对于括号里面的第二项,可以视为一个子问题递归处理,即得:

ans=nm1n1+12(nm(nm11)+nm(nm21)+...+nm(n1))

=nm1n1+12nmi=1m1(ni1)

=nm1n1+nm2(nm1n1m)

快速幂+逆元即可。

代码:

#include<cstdio>#include<algorithm>#include<cstring>#include<queue>using namespace std;typedef long long ll;const ll mod = 1e9 + 7;ll fast_pow(ll n,ll m){    ll res = 1;    while(m){        if(m&1) res = res*n%mod;        n = n*n%mod;        m >>= 1;    }    return res;}int main(){    ll n,m;    scanf("%lld%lld",&n,&m);    ll res = (fast_pow(n,m)-1)*fast_pow(n-1,mod-2)%mod;    ll ans = (res + (fast_pow(n,m)*fast_pow(2,mod-2)%mod*(res-m)%mod))%mod;    if(ans<0) ans += mod;    printf("%lld\n",ans);    return 0;}
原创粉丝点击