zoukankan      html  css  js  c++  java
  • 【莫比乌斯反演】BZOJ2154 Crash的数字表格

    Description

      求sigma lcm(x,y),x<=n,y<=m。n,m<=1e7。

    Solution

      lcm没有什么直接做的好方法,用lcm=x*y/gcd转成gcd来做

      就是要求sigma d*f(x/d,y/d)

      f(x,y)为x和y以内gcd正好为1的对数

      F为所有对数,于是有F(x,y)=x*(x+1)/2*y*(y+1)/2

      f(x,y)=sigma (1<=i<=x) i*i*mu(i)*F(x/i,y/i) 

      f用莫比乌斯反演解决,这两个式子都套上分块优化到sqrt,于是总复杂度sqrt*sqrt=n

      分块优化具体可以见上一篇blog

    Code

      一开始全开LL MLE了一发

      然后又WA了两发,第一次是有一地方算的时候溢出

      一开始为了避免MLE把prime数组/50,但其实只能/20的样子

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #define ll long long
     5 using namespace std;
     6 const int maxn=1e7+5,mod=20101009;
     7 
     8 bool flag[maxn];
     9 int prime[maxn],mu[maxn],cnt;
    10 int sum[maxn],s[maxn];
    11 int n,m;
    12 
    13 void getmu(){
    14     mu[1]=1;
    15     for(int i=2;i<=n;i++){
    16         if(!flag[i]){
    17             mu[i]=-1;
    18             prime[++cnt]=i;
    19         }
    20         for(int j=1;i*prime[j]<=n&&j<=cnt;j++){
    21             flag[i*prime[j]]=1;
    22             if(i%prime[j]==0){
    23                 mu[i*prime[j]]=0;
    24                 break;
    25             }
    26             mu[i*prime[j]]=-mu[i];
    27         }
    28     }
    29     for(int i=1;i<=n;i++)
    30         sum[i]=(sum[i-1]+(ll)i*i*mu[i]%mod)%mod;
    31 }
    32 
    33 ll F(int x,int y){
    34     return (ll)((ll)x*(x+1)/2%mod)*((ll)y*(y+1)/2%mod)%mod;
    35 }
    36 
    37 ll f(int x,int y){
    38     ll ret=0;
    39     int p;
    40     for(int i=1;i<=x;i=p+1){
    41         p=min(x/(x/i),y/(y/i));
    42         ret=(ret+(ll)(sum[p]-sum[i-1])*F(x/i,y/i))%mod;
    43     }
    44     return ret;
    45 }
    46 
    47 int main(){
    48     scanf("%d%d",&n,&m);
    49     if(n>m) swap(n,m);
    50     for(int i=1;i<=n;i++) s[i]=(s[i-1]+i)%mod;
    51     getmu();
    52     
    53     int pos;
    54     ll ans=0;
    55     for(int i=1;i<=n;i=pos+1){
    56         pos=min(n/(n/i),m/(m/i));
    57         ans=(ans+(ll)(s[pos]-s[i-1])*f(n/i,m/i))%mod;
    58     }
    59     printf("%lld
    ",(ans+mod)%mod);
    60     return 0;
    61 }
  • 相关阅读:
    个人博客
    个人博客
    个人博客
    个人博客
    个人博客
    个人博客
    个人博客
    5.14
    5.13
    5.12
  • 原文地址:https://www.cnblogs.com/xkui/p/4597275.html
Copyright © 2011-2022 走看看