• hdu1695(莫比乌斯)或欧拉函数+容斥


    题意:求1-b和1-d之内各选一个数组成数对。问最大公约数为k的数对有多少个,数对是有序的。(b,d,k<=100000)


    解法1: 这个能够简化成1-b/k 和1-d/k 的互质有序数对的个数。

    如果b=b/k。d=d/k,b<=d.欧拉函数能够算出1-b与1-b之内的互质对数。然后在b+1到d的数i,求每一个i在1-b之间有多少互质的数。

    解法是容斥,getans函数參数的意义:1-tool中含有rem位置之后的i的质因子的数的个数。

    for(int j=rem;j<=factor[i][0];j++)
        ans+=tool/factor[i][j]-getnum(i,tool/factor[i][j],j+1);
    这个循环中。ans加的等号后每项表示当前最大的质因子是factor[i][j]的数量,目的是去重。


    解法2:莫比乌斯,莫比乌斯数组确实非常实用。事实上也非常easy,mou的位置的含义是,首先假设i有个质因子出现2次或以上。则mou值为0,否则1与-1跟i的质因子奇偶性决定。目的也是容斥。


    解法1代码:

    /******************************************************
    * @author:xiefubao
    *******************************************************/
    #pragma comment(linker, "/STACK:102400000,102400000")
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <queue>
    #include <vector>
    #include <algorithm>
    #include <cmath>
    #include <map>
    #include <set>
    #include <stack>
    #include <string.h>
    //freopen ("in.txt" , "r" , stdin);
    using namespace std;
    
    #define eps 1e-8
    #define zero(_) (abs(_)<=eps)
    const double pi=acos(-1.0);
    typedef long long LL;
    const int Max=100010;
    const LL INF=0x3FFFFFFF;
    int a, b, c, d, k;
    int factor[Max][20];
    bool rem[Max];
    LL oular[Max];
    void init()
    {
        for(int i=1; i<Max; i++)
            oular[i]=i;
        for(LL i=2; i<Max; i++)
        {
            if(!rem[i])
            {
                factor[i][++factor[i][0]]=i;
                 oular[i]=i-1;
                for(LL j=i*2; j<Max; j+=i)
                {
                    factor[j][++factor[j][0]]=i;
                    rem[j]=1;
                    oular[j]=oular[j]*(i-1)/i;
                }
            }
        }
        for(int i=1; i<Max; i++)
            oular[i]=oular[i]+oular[i-1];
    }
    LL getnum(int i,int tool,int rem)
    {
        int ans=0;
        for(int j=rem;j<=factor[i][0];j++)
        ans+=tool/factor[i][j]-getnum(i,tool/factor[i][j],j+1);
        return ans;
    }
    int main()
    {
        int t;
        cin>>t;
        init();int kk=1;
        while(t--)
        {
            cin>>a>>b>>c>>d>>k;
            printf("Case %d: ",kk++);
            if(k==0)
            {
                cout<<"0
    ";
                continue;
            }
            b/=k;
            d/=k;
            if(b>d)swap(b,d);
            LL ans=oular[b];
            for(int i=b+1;i<=d;i++)
            {
                ans+=b-getnum(i,b,1);
            }
            cout<<ans<<endl;
        }
        return 0;
    }
    解法2代码:
    /******************************************************
    * @author:xiefubao
    *******************************************************/
    #pragma comment(linker, "/STACK:102400000,102400000")
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <queue>
    #include <vector>
    #include <algorithm>
    #include <cmath>
    #include <map>
    #include <set>
    #include <stack>
    #include <string.h>
    //freopen ("in.txt" , "r" , stdin);
    using namespace std;
    
    #define eps 1e-8
    #define zero(_) (abs(_)<=eps)
    const double pi=acos(-1.0);
    typedef long long LL;
    const int Max=100010;
    const LL INF=0x3FFFFFFF;
    int a, b, c, d, k;
    bool rem[Max];
    int mou[Max];
    void init()
    {
        mou[1]=1;
        for(LL i=2; i<Max; i++)
        {
            if(!rem[i])
            {
                mou[i]=i;
                for(LL j=i*2; j<Max; j+=i)
                {
                    rem[j]=1;
                    mou[j]=i;
                }
            }
        }
        for(int i=2; i<Max; i++)
        {
            if(i/mou[i]%mou[i]==0) mou[i]=0;
            else mou[i]=-mou[i/mou[i]];
        }
    }
    int main()
    {
        int t;
        cin>>t;
        init();
        int kk=1;
        while(t--)
        {
            cin>>a>>b>>c>>d>>k;
            printf("Case %d: ",kk++);
            if(k==0)
            {
                cout<<"0
    ";
                continue;
            }
            b/=k;
            d/=k;
            if(b > d)swap(b,d);
            long long ans1 = 0;
            for(int i = 1; i <= b; i++)
                ans1 += (long long)mou[i]*(b/i)*(d/i);
            long long ans2 = 0;
            for(int i = 1; i <= b; i++)
                ans2 += (long long)mou[i]*(b/i)*(b/i);
            ans1 -= ans2/2;
            cout<<ans1<<endl;
        }
        return 0;
    }


  • 相关阅读:
    [硬件驱动_蓝牙]蓝牙Bluez的编程实现
    二分查找
    LeetCode-35.Search Insert Position
    LeetCode-34.Find First and Last Position of Element in Sorted Array
    LeetCode-704.Binary Search
    剑指offer-最小的k个数
    树的各种遍历
    LeetCode-912.Sort an Array
    排序
    LeetCode-209.Minimum Size Subarray Sum
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/5182360.html
Copyright © 2020-2023  润新知