[关闭]
@xiaoziyao 2020-05-23T04:59:41.000000Z 字数 3337 阅读 997

P4449 于神之怒加强版解题报告

解题报告


备注:为质数集,为自然数集。

P4449 于神之怒加强版解题报告:

更好的阅读体验

题意:给定,后有组数据给定,求。数据范围:

我们可以先给原式变换一下形式(以下默认):

首先套路性地枚举(中括号内的是一个有点像的东西)
可以发现造成贡献的都是,那么肯定是的倍数,我们就将缩小倍:
然后莫比乌斯反演():
由于的因数,因此一定是的公因数,仿照上面,我们将缩小倍(顺便改变一下运算顺序):
稍微做一下变形:
然后我们可以设(这样我们可以把的枚举变为枚举的因数),然后可以得到:
,则原式化为:
然后我们用整除分块可以做到的时间,于是我们的目标转移到如何线性筛预处理函数:
由两个积性函数(
的狄利克雷卷积也是一个积性函数,我们可以构造的标准分解得到,于是我们转而计算一个质数的幂次方。
由莫比乌斯函数的性质(如果一个数是一个完全平方数的倍数,那么,这是莫比乌斯函数的定义)可得,当
因此很显然有:
然后我们考虑求,发现
最后,我们讨论一下如何线性筛(求):
时,取的幂次,则由的积性有
由上文求出的得再用的积性合并得:
时,直接由的积性可得
综上所述
故线性筛+数论分块即可。

代码:

  1. #include<stdio.h>
  2. const long long maxn=5000005,mod=1000000007;
  3. long long i,j,k,m,n,T,cnt,l,r,ans;
  4. long long a[maxn],p[maxn],f[maxn],pf[maxn];
  5. inline long long min(long long a,long long b){
  6. return a<b? a:b;
  7. }
  8. long long ksm(long long a,long long b){
  9. long long res=1;
  10. while(b){
  11. if(b&1)
  12. res=(res*a)%mod;
  13. a=(a*a)%mod,b>>=1;
  14. }
  15. return res;
  16. }
  17. int main(){
  18. scanf("%lld%lld",&T,&k);
  19. p[1]=f[1]=1;
  20. for(i=2;i<maxn;i++){
  21. if(p[i]==0)
  22. a[++cnt]=i,f[i]=(ksm(i,k)-1+mod)%mod;
  23. for(j=1;j<=cnt;j++){
  24. if(i*a[j]>=maxn)
  25. break;
  26. p[i*a[j]]=1;
  27. if(i%a[j]==0){
  28. f[i*a[j]]=f[i]*ksm(a[j],k)%mod;
  29. break;
  30. }
  31. f[i*a[j]]=f[i]*f[a[j]]%mod;
  32. }
  33. }
  34. for(i=1;i<maxn;i++)
  35. pf[i]=pf[i-1]+f[i];
  36. while(T--){
  37. scanf("%lld%lld",&n,&m);
  38. l=1,ans=0;
  39. while(l<=min(n,m)){
  40. r=min(n/(n/l),m/(m/l));
  41. ans=((ans+(pf[r]-pf[l-1]+mod)%mod*(n/l)%mod*(m/l)%mod)%mod+mod)%mod;
  42. l=r+1;
  43. }
  44. printf("%lld\n",ans);
  45. }
  46. return 0;
  47. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注