[关闭]
@11101001 2018-03-24T21:10:50.000000Z 字数 2324 阅读 852

bzoj4816: [Sdoi2017]数字表格

莫比乌斯反演


题目链接

bzoj4816: [Sdoi2017]数字表格

题解

满满的反演的套路的味道


常规操作枚举约数

上面的式子可以化为

对于


很眼熟...推下式子



那么原式变成了

对于每个,令,的值是固定的,用筛法求出,做前缀积,对与数论分块一下
复杂度为

代码

  1. // luogu-judger-enable-o2
  2. #include<cstdio>
  3. #include<algorithm>
  4. const int maxn = 1000007;
  5. const int mod = 1e9+7;
  6. int f[maxn+7],invf[maxn+7],F[maxn+7];
  7. bool isprime[maxn+7];int mu[maxn+7],prime[maxn+7],num;
  8. int pow(int a,int p) {
  9. int ret=1;
  10. for(;p;p>>=1,a=(1LL*a*a)%mod){
  11. if(p&1) ret=(1LL*ret*a)%mod;
  12. }
  13. return ret;
  14. }
  15. void init() {
  16. f[1]=1;
  17. for(int i=2;i<maxn;++i) f[i]=(f[i-1]+f[i-2])%mod;
  18. for(int i=1;i<maxn;++i) {
  19. invf[i]=pow(f[i],mod-2)%mod;
  20. //printf("%d %d\n",invf[i],f[i]);
  21. }
  22. isprime[1]=1;mu[1]=1;F[0]=F[1]=1;
  23. //printf("%d\n",mu[1]);
  24. for(int i=2;i<=maxn-7;++i) {
  25. F[i]=1;
  26. if(!isprime[i]) prime[++num]=i,mu[i]=-1;
  27. for(int j=1;j<=num&&prime[j]*i<=maxn-7;++j) {
  28. isprime[i*prime[j]]=1;
  29. if(i%prime[j]==0) {mu[i*prime[j]]=0;break;}
  30. else mu[i*prime[j]]=-mu[i];
  31. }
  32. }
  33. for(int i=1;i<=maxn-7;++i) {
  34. if(mu[i]==0)continue;
  35. for(int j=i;j<=maxn-7;j+=i) {
  36. if(mu[i]==1) F[j]=(1ll*F[j]*f[j/i])%mod;
  37. if(mu[i]==-1) F[j]=(1ll*F[j]*invf[j/i])%mod;
  38. }
  39. }
  40. for(int i=1;i<=maxn-7;++i) F[i]=(1ll*F[i]*F[i-1])%mod;//,printf("%d\n",F[i]);
  41. }
  42. int query(int a,int b) {
  43. int n=std::min(a,b);long long ans=1;
  44. for(int nxt,i=1;i<=n;i=nxt+1) {
  45. nxt=std::min(a/(a/i),b/(b/i));
  46. long long tmp=1ll*F[nxt]*pow(F[i-1],mod-2)%mod;
  47. ans=(1ll*ans*pow(tmp,1ll*(a/i)*(b/i)%(mod-1)))%mod;
  48. }
  49. return (ans+mod)%mod;
  50. }
  51. int main() {
  52. //freopen("001.out","w",stdout);
  53. init();
  54. int T;scanf("%d",&T);
  55. for(int a,b;T--;) {
  56. scanf("%d%d",&a,&b);
  57. printf("%d\n",query(a,b));
  58. }
  59. return 0;
  60. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注