[关闭]
@xiaoziyao 2020-05-04T12:39:00.000000Z 字数 4845 阅读 1161

简单的数学题解题报告

解题报告


简单的数学题解题报告:

题意:求

数据范围:,保证为质数

做这道题前,请保证你已经学会莫比乌斯反演和杜教筛0,否则可以到我博珂里康康:
狄利克雷卷积&莫比乌斯反演学习笔记
杜教筛学习笔记

开始推式子:


,即加到的和
因此:

用狄利克雷卷积推一下:

因此继续化简:


我们很容易看出是积性函数,因为:
由于为积性函数,若,则相乘得:

因此我们可以用杜教筛来处理的前缀和,原式化为:,此时原式可以数论分块来做
考虑如何筛,我们设另一个数论函数为,则它们的卷积为:
我们尝试用消去这个项,设,然后可以推出来:

由欧拉反演得:

因此可以用杜教筛的式子,设的前缀和:

我们可以用小学奥数的思路推一下
首先,因此:

那么肯定也很显然了,就不推了,最终的式子为
代入杜教筛的式子得:

用数论分块和递归可以在很快的时间内用计算出
然后预处理一些就可以了
最后代入原式:

然后数论分块就结束了

代码:

  1. #include<stdio.h>
  2. #include<map>
  3. using namespace std;
  4. const long long maxn=5000005;
  5. long long i,j,k,m,n,mod,cnt,inv6;
  6. long long a[maxn],p[maxn],varphi[maxn],S[maxn];
  7. map<long long,long long>ans;
  8. inline long long getsum(long long n){
  9. return n*(n+1)/2%mod;
  10. }
  11. inline long long calc(long long n){
  12. return n*(n+1)%mod*(2*n+1)%mod*inv6%mod;
  13. }
  14. long long ksm(long long a,long long b,long long mod){
  15. long long res=1;
  16. while(b){
  17. if(b&1)
  18. res=(res*a)%mod;
  19. a=(a*a)%mod,b>>=1;
  20. }
  21. return res;
  22. }
  23. long long getS(long long n){
  24. if(n<maxn)
  25. return S[n];
  26. if(ans.count(n))
  27. return ans[n];
  28. long long l=2,r,res=getsum(n)*getsum(n)%mod;
  29. while(l<=n){
  30. r=n/(n/l);
  31. res=((res-(calc(r)-calc(l-1)+mod)%mod*getS(n/l)%mod)%mod+mod)%mod;
  32. l=r+1;
  33. }
  34. res=(res%mod+mod)%mod;
  35. return ans[n]=res;
  36. }
  37. long long getans(long long n){
  38. long long l=1,r,res=0;
  39. while(l<=n){
  40. r=n/(n/l);
  41. res=(res+(getS(r)-getS(l-1)+mod)%mod*getsum(n/l)%mod*getsum(n/l)%mod)%mod;
  42. l=r+1;
  43. }
  44. res=(res%mod+mod)%mod;
  45. return res;
  46. }
  47. int main(){
  48. scanf("%lld%lld",&mod,&n);
  49. inv6=ksm(6,mod-2,mod);
  50. p[1]=varphi[1]=1;
  51. for(i=2;i<maxn;i++){
  52. if(p[i]==0)
  53. a[++cnt]=i,varphi[i]=i-1;
  54. for(j=1;j<=cnt;j++){
  55. if(i*a[j]>=maxn)
  56. break;
  57. p[i*a[j]]=1;
  58. if(i%a[j]==0){
  59. varphi[i*a[j]]=varphi[i]*a[j];
  60. break;
  61. }
  62. varphi[i*a[j]]=varphi[i]*(a[j]-1);
  63. }
  64. }
  65. for(i=1;i<maxn;i++)
  66. S[i]=(S[i-1]+varphi[i]%mod*i%mod*i%mod)%mod;
  67. printf("%lld\n",getans(n));
  68. return 0;
  69. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注