zoukankan      html  css  js  c++  java
  • 莫比乌斯函数+莫比乌斯反演

    几个经典的莫比乌斯反演练习题

    先来一个莫比乌斯函数板子

     1 int N = 10000000;
     2 int not_prim[10000050],prim[10000050];
     3 long long mu[10000050],tot;
     4 void getmu(long long n){
     5     not_prim[0] = not_prim[1] = 1;
     6     mu[1] = 1;
     7     for (long long i = 2 ; i<= n; i++){
     8         if (!not_prim[i]){
     9             mu[i] = -1;
    10             prim[++tot] = i;
    11         }
    12         for (long long j = 1; j <= tot && prim[j]*i <= n ; j++){
    13             not_prim[prim[j]*i] = i;
    14             if (i % prim[j] == 0){
    15                 mu[prim[j]*i] = 0;
    16                 break;
    17             }
    18             mu[prim[j]*i] =-mu[i];
    19         }
    20     }
    21 }

    几个例题

    BZOJ2154

    #include <bits/stdc++.h>
    const long long mod = 20101009;
    const double ex = 1e-10;
    #define inf 0x3f3f3f3f
    using namespace std;
    int T;
    int N = 10000000;
    int not_prim[10000050],prim[10000050];
    long long mu[10000050],tot;
    long long sum_mu[10000050];
    void getmu(long long n){
        not_prim[0] = not_prim[1] = 1;
        mu[1] = 1;
        for (long long i = 2 ; i<= n; i++){
            if (!not_prim[i]){
                mu[i] = -1;
                prim[++tot] = i;
            }
            for (long long j = 1; j <= tot && prim[j]*i <= n ; j++){
                not_prim[prim[j]*i] = i;
                if (i % prim[j] == 0){
                    mu[prim[j]*i] = 0;
                    break;
                }
                mu[prim[j]*i] =-mu[i];
            }
        }
        for (int i = 1 ; i <= n ; i++){
            sum_mu[i] = (sum_mu[i-1] + (mu[i] * i * i  % mod) + mod ) % mod;
        }
    }
    inline long long sum(long long m,long long n){
        return ((m*(m+1)/2LL) % mod) * ((n*(n+1)/2LL) % mod) % mod;
    }
    inline long long F(long long m,long long n){
        if (n > m) swap(n,m);
        long long nex;
        long long ans = 0;
        for (long long i = 1LL;i<=n; i = nex + 1LL){
            nex = min(n/(n/i),m/(m/i));
            long long tmp1 = ( (sum_mu[nex] - sum_mu[i-1])  % mod + mod ) % mod;
            ans = (ans + ( sum(m/i,n/i) * tmp1 % mod ) )% mod;
        }
        return ans;
    }
    long long solve(long long n,long long m){
        long long ans = 0;
        if (n > m) swap(n,m);
        long long nex;
        for (long long i = 1 ; i<=n ; i = nex+1){
            nex = min(m/(m/i),n/(n/i));
            long long tmp = ((i+nex)*(nex-i+1LL)/2LL) % mod;
            ans = (ans + (tmp * F(n/i,m/i)) % mod) % mod;
        }
        return ans;
    }
    int main(){
        long long m,n;
        scanf("%lld%lld",&m,&n);
        getmu(min(n,m));
        printf("%lld
    ",solve(m,n));
    }
    View Code

    BZOJ2301

    #include <bits/stdc++.h>
    const long long mod = 1e9+7;
    const double ex = 1e-10;
    #define inf 0x3f3f3f3f
    using namespace std;
    int not_prim[200050],prim[200050],mu[200050],tot,sum_mu[200050];
    long long x;
    void getmu(int n){
        not_prim[0] = not_prim[1] = 1;
        mu[1] = 1;
        for (int i = 2 ; i<= n; i++){
            if (!not_prim[i]){
                mu[i] = -1;
                prim[++tot] = i;
            }
            for (int j = 1; j <= tot && prim[j]*i <= n ; j++){
                not_prim[prim[j]*i] = i;
                if (i % prim[j] == 0){
                    mu[prim[j]*i] = 0;
                    break;
                }
                mu[prim[j]*i] =-mu[i];
            }
        }
        for (int i = 1 ; i <= n ; i++){
            sum_mu[i] = sum_mu[i-1] + mu[i];
        }
    }
    int solve(int n,int m,int x){
        int ans = 0;
        int nex;
        if (n>m) swap(n,m);
        for (int i = 1 ; i*x<=n ; i = nex+1){
            nex = min(n/(n/(i*x)),m/(m/(i*x)))/x;
            ans += (n/(i*x)) * (m/(i*x)) * (sum_mu[nex] - sum_mu[i-1]);
        }
        return ans;
    }
    int main()
    {
        int T;
        cin >> T;
        getmu(50050);
        while (T--){
            int a,b,c,d,k;
            scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
            int ans = solve(b,d,k) - solve(a-1,d,k) - solve(b,c-1,k) + solve(a-1,c-1,k);
            printf("%d
    ",ans);
        }
    }
    View Code

    BZOJ2440

    #include <bits/stdc++.h>
    const long long mod = 1e9+7;
    const double ex = 1e-10;
    #define inf 0x3f3f3f3f
    using namespace std;
    int not_prim[200050],prim[2000050],mu[2000050],tot;
    long long x;
    void getmu(int n){
        not_prim[0] = not_prim[1] = 1;
        mu[1] = 1;
        for (int i = 2 ; i<= n; i++){
            if (!not_prim[i]){
                mu[i] = -1;
                prim[++tot] = i;
            }
            for (int j = 1; j <= tot && prim[j]*i <= n ; j++){
                not_prim[prim[j]*i] = i;
                if (i % prim[j] == 0){
                    mu[prim[j]*i] = 0;
                    break;
                }
                mu[prim[j]*i] =-mu[i];
            }
        }
    }
    bool check(long long mid){
        long long ans = mid;
        for (long long i = 2 ; i * i <= mid ;i++ ){
            ans += mu[i]*(mid/(i*i));
        }
        return ans >= x;
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        getmu(200000);
        while (T--){
    
            scanf("%I64d",&x);
            long long r = 1;
            long long l = 1e10;
            long long ans = 1;
            while (r <= l){
                long long mid = ( r + l ) >> 1;
                if (check(mid)){
                    ans = mid;
                    l = mid - 1;
                }
                else r = mid + 1;
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    View Code

    BZOJ2820

    #include <bits/stdc++.h>
    const long long mod = 1e9+7;
    const double ex = 1e-10;
    #define inf 0x3f3f3f3f
    using namespace std;
    long long not_prim[10000050],prim[10000050],mu[10000050],tot;
    void getmu(long long n){
        not_prim[0] = not_prim[1] = 1LL;
        mu[1] = 1LL;
        for (long long i = 2LL ; i<= n; i++){
            if (!not_prim[i]){
                mu[i] = -1;
                prim[++tot] = i;
            }
            for (long long j = 1; j <= tot && prim[j]*i <= n ; j++){
                not_prim[prim[j]*i] = i;
                if (i % prim[j] == 0LL){
                    mu[prim[j]*i] = 0LL;
                    break;
                }
                mu[prim[j]*i] =-mu[i];
            }
        }
    }
    long long c[10000050];
    void init(long long n){
        for (long long i = 1; i<=tot ;i++){
            for (long long j = prim[i] ; j <= n; j+=prim[i]){
                c[j] += mu[j/prim[i]];
            }
        }
        for (long long i = 1 ; i<=n; i++)
            c[i] += c[i-1];
    }
    long long solve(long long n,long long m){
        long long ans = 0;
        long long nex;
        if (n>m) swap(n,m);
        for (long long i = 1; i<=n ; i=nex+1){
            nex = min(n/(n/i),m/(m/i));
            ans += (n/i)*(m/i)*(c[nex]-c[i-1]);
        }
        return ans;
    }
    int main(){
        int T;
        scanf("%d",&T);
        getmu(10000001);
        init(10000001);
        while (T--){
            long long n,m;
            scanf("%lld%lld",&n,&m);
            printf("%lld
    ",solve(n,m));
        }
    }
    View Code

    BZOJ3529

    #include <bits/stdc++.h>
    const unsigned int mod = 1LL<<31;
    const double ex = 1e-10;
    #define inf 0x3f3f3f3f
    using namespace std;
    int T;
    int N = 100000;
    int not_prim[100050],prim[100050],mu[100050],tot;
    void getmu(int n){
        not_prim[0] = not_prim[1] = 1LL;
        mu[1] = 1LL;
        for (int i = 2LL ; i<= n; i++){
            if (!not_prim[i]){
                mu[i] = -1;
                prim[++tot] = i;
            }
            for (int j = 1; j <= tot && prim[j]*i <= n ; j++){
                not_prim[prim[j]*i] = i;
                if (i % prim[j] == 0LL){
                    mu[prim[j]*i] = 0LL;
                    break;
                }
                mu[prim[j]*i] =-mu[i];
            }
        }
    }
    struct node{
        int i;
        unsigned int fi;
    }F[100050];
    unsigned int c[100050];
    int lowbit(int k){
        return k&(-k);
    }
    void Modify(int num,unsigned int v){
        while (num<=N){
            c[num]= c[num] + v ;
            num+=lowbit(num);
        }
    }
    unsigned int Sum(int num){
        long long ans = 0;
        while (num != 0){
            ans=ans + c[num];
            num-=lowbit(num);
        }
        return ans;
    }
    void initF(int n){
        for (int i = 1; i<=n ; i++){
            for (int j = i; j<=n; j+=i){
                F[j].fi=F[j].fi + i;
            }
            F[i].i = i;
        }
    }
    struct quer{
        int n,m;
        int a;
        int id;
        unsigned int ans;
    }Q[20022];
    inline bool cmpa(quer a,quer b){
        return a.a < b.a;
    }
    inline bool cmpid(quer a,quer b){
        return a.id < b.id;
    }
    inline bool cmp(node a,node b){
        return a.fi < b.fi;
    }
    void solve(int n){
        sort(Q+1,Q+T+1,cmpa);
        sort(F+1,F+N+1,cmp);
        int j = 0;
        for (int i = 1; i<=T; i++){
            while (j+1<=n&&F[j+1].fi<=Q[i].a){
                j++;
                for (int k = F[j].i ; k<=n ; k+=F[j].i){
                    Modify(k,F[j].fi * mu[k/F[j].i]);
                }
            }
            int n,m;
            n=Q[i].n;
            m=Q[i].m;
            if (n > m ) swap(m,n);
            int nex;
            unsigned int ans = 0;
            for (int k = 1; k<=n; k = nex+1){
                nex = min(n/(n/k),m/(m/k));
                ans = ans + (n/k) * (m/k)  * (Sum(nex) - Sum(k-1));
            }
            Q[i].ans = ans;
        }
        sort(Q+1,Q+T+1,cmpid);
    }
    int main(){
        getmu(100000);
        initF(100000);
        scanf("%d",&T);
        for (int i = 1; i<=T; i++)
            scanf("%d%d%d",&Q[i].n,&Q[i].m,&Q[i].a),Q[i].id = i;
        solve(100000);
        for (int i = 1; i<=T; i++){
            printf("%d
    ",Q[i].ans%mod);
        }
        return 0;
    }
    View Code

    BZOJ2693

      1 #include <bits/stdc++.h>
      2 const int mod = 100000009;
      3 const double ex = 1e-10;
      4 #define inf 0x3f3f3f3f
      5 using namespace std;
      6 int N = 10000000;
      7 int not_prim[10000050],prim[10000050];
      8 int mu[10000050],tot;
      9 int pre[10000050];
     10 namespace fastIO{
     11     #define BUF_SIZE 100000
     12     #define OUT_SIZE 100000
     13     #define ll long long
     14     //fread->read
     15     bool IOerror=0;
     16     inline char nc(){
     17         static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
     18         if (p1==pend){
     19             p1=buf; pend=buf+fread(buf,1,BUF_SIZE,stdin);
     20             if (pend==p1){IOerror=1;return -1;}
     21             //{printf("IO error!
    ");system("pause");for (;;);exit(0);}
     22         }
     23         return *p1++;
     24     }
     25     inline bool blank(char ch){return ch==' '||ch=='
    '||ch=='
    '||ch=='	';}
     26     inline int read(int &x){
     27         bool sign=0; char ch=nc(); x=0;
     28         for (;blank(ch);ch=nc());
     29         if (IOerror)return 0;
     30         if (ch=='-')sign=1,ch=nc();
     31         for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
     32         if (sign)x=-x;
     33         return 1;
     34     }
     35     inline int read(ll &x){
     36         bool sign=0; char ch=nc(); x=0;
     37         for (;blank(ch);ch=nc());
     38         if (IOerror)return 0;
     39         if (ch=='-')sign=1,ch=nc();
     40         for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
     41         if (sign)x=-x;
     42         return 1;
     43     }
     44     inline int read(double &x){
     45         bool sign=0; char ch=nc(); x=0;
     46         for (;blank(ch);ch=nc());
     47         if (IOerror)return 0;
     48         if (ch=='-')sign=1,ch=nc();
     49         for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
     50         if (ch=='.'){
     51             double tmp=1; ch=nc();
     52             for (;ch>='0'&&ch<='9';ch=nc())tmp/=10.0,x+=tmp*(ch-'0');
     53         }
     54         if (sign)x=-x;
     55         return 1;
     56     }
     57     inline int read(char *s){
     58         char ch=nc();
     59         for (;blank(ch);ch=nc());
     60         if (IOerror)return 0;
     61         for (;!blank(ch)&&!IOerror;ch=nc())*s++=ch;
     62         *s=0;
     63         return 1;
     64     }
     65     inline void read(char &c){
     66         for (c=nc();blank(c);c=nc());
     67         if (IOerror){c=-1;return;}
     68     }
     69     //fwrite->write
     70     struct Ostream_fwrite{
     71         char *buf,*p1,*pend;
     72         Ostream_fwrite(){buf=new char[BUF_SIZE];p1=buf;pend=buf+BUF_SIZE;}
     73         void out(char ch){
     74             if (p1==pend){
     75                 fwrite(buf,1,BUF_SIZE,stdout);p1=buf;
     76             }
     77             *p1++=ch;
     78         }
     79         void print(int x){
     80             static char s[15],*s1;s1=s;
     81             if (!x)*s1++='0';if (x<0)out('-'),x=-x;
     82             while(x)*s1++=x%10+'0',x/=10;
     83             while(s1--!=s)out(*s1);
     84         }
     85         void println(int x){
     86             static char s[15],*s1;s1=s;
     87             if (!x)*s1++='0';if (x<0)out('-'),x=-x;
     88             while(x)*s1++=x%10+'0',x/=10;
     89             while(s1--!=s)out(*s1); out('
    ');
     90         }
     91         void print(ll x){
     92             static char s[25],*s1;s1=s;
     93             if (!x)*s1++='0';if (x<0)out('-'),x=-x;
     94             while(x)*s1++=x%10+'0',x/=10;
     95             while(s1--!=s)out(*s1);
     96         }
     97         void println(ll x){
     98             static char s[25],*s1;s1=s;
     99             if (!x)*s1++='0';if (x<0)out('-'),x=-x;
    100             while(x)*s1++=x%10+'0',x/=10;
    101             while(s1--!=s)out(*s1); out('
    ');
    102         }
    103         void print(double x,int y){
    104             static ll mul[]={1,10,100,1000,10000,100000,1000000,10000000,100000000,
    105                 1000000000,10000000000LL,100000000000LL,1000000000000LL,10000000000000LL,
    106                 100000000000000LL,1000000000000000LL,10000000000000000LL,100000000000000000LL};
    107             if (x<-1e-12)out('-'),x=-x;x*=mul[y];
    108             ll x1=(ll)floor(x); if (x-floor(x)>=0.5)++x1;
    109             ll x2=x1/mul[y],x3=x1-x2*mul[y]; print(x2);
    110             if (y>0){out('.'); for (size_t i=1;i<y&&x3*mul[i]<mul[y];out('0'),++i); print(x3);}
    111         }
    112         void println(double x,int y){print(x,y);out('
    ');}
    113         void print(char *s){while (*s)out(*s++);}
    114         void println(char *s){while (*s)out(*s++);out('
    ');}
    115         void flush(){if (p1!=buf){fwrite(buf,1,p1-buf,stdout);p1=buf;}}
    116         ~Ostream_fwrite(){flush();}
    117     }Ostream;
    118     inline void print(int x){Ostream.print(x);}
    119     inline void println(int x){Ostream.println(x);}
    120     inline void print(char x){Ostream.out(x);}
    121     inline void println(char x){Ostream.out(x);Ostream.out('
    ');}
    122     inline void print(ll x){Ostream.print(x);}
    123     inline void println(ll x){Ostream.println(x);}
    124     inline void print(double x,int y){Ostream.print(x,y);}
    125     inline void println(double x,int y){Ostream.println(x,y);}
    126     inline void print(char *s){Ostream.print(s);}
    127     inline void println(char *s){Ostream.println(s);}
    128     inline void println(){Ostream.out('
    ');}
    129     inline void flush(){Ostream.flush();}
    130 };
    131 using namespace fastIO;
    132 
    133 inline void getmu(int n){
    134     not_prim[0] = not_prim[1] = 1;
    135     mu[1] = 1;
    136     for (int i = 2 ; i<= n; i++){
    137         if (!not_prim[i]){
    138             mu[i] = -1;
    139             prim[++tot] = i;
    140         }
    141         for (int j = 1; j <= tot && prim[j]*i <= n ; j++){
    142             not_prim[prim[j]*i] = i;
    143             if (i % prim[j] == 0){
    144                 mu[prim[j]*i] = 0;
    145                 break;
    146             }
    147             mu[prim[j]*i] =-mu[i];
    148         }
    149     }
    150 }
    151 inline void getpre(int n){
    152     for (int i = 1; i<=n ;i++){
    153         if (mu[i]==0) continue;
    154         for (long long j = i ; j<=n ; j+=i){
    155             pre[j] = (pre[j] + mu[i] * i + mod) % mod;
    156         }
    157     }
    158     for (int i = 1; i<=n ;i++){
    159         pre[i] = ( pre[i-1] + (int)((long long)pre[i]*(long long)i % mod ) ) % mod;
    160     }
    161 }
    162 inline long long sum(long long m,long long n){
    163     return ((m*(m+1)/2LL) % mod) * ((n*(n+1)/2LL) % mod) % mod;
    164 }
    165 inline int solve(int  n,int  m){
    166     if (n > m) swap(n,m);
    167     int nex;
    168     int ans = 0;
    169     for (long long i = 1 ; i <= n ; i = nex+1){
    170         nex = min(n/(n/i),m/(m/i));
    171         ans = (ans + (int)(( sum(n/i,m/i) * (long long)(pre[nex] - pre[i-1] + mod) ) % mod)  ) % mod;
    172     }
    173     return ans;
    174 }
    175 int main()
    176 {
    177 
    178     int T;
    179     scanf("%d",&T);
    180     getmu(N);
    181     getpre(N);
    182     while (T--){
    183         long long n,m;
    184         read(n);
    185         read(m);
    186         print(solve(n,m));
    187         print('
    ');
    188     }
    189     return 0;
    190 }
    卡常数。
  • 相关阅读:
    Beta版使用说明
    【每日scrum】NO.7
    【每日scrum】NO.6
    【每日scrum】NO.5
    【每日scrum】NO.4
    【每日scrum】NO.3
    【每日scrum】NO.2
    【每日scrum】NO.1
    运行及总结
    测试与调试
  • 原文地址:https://www.cnblogs.com/HITLJR/p/7421799.html
Copyright © 2011-2022 走看看