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:莫比乌斯,莫比乌斯数组确实很有用。其实也很简单,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\n";
            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\n";
            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;
}
时间: 2024-10-13 12:26:48

hdu1695(莫比乌斯)或欧拉函数+容斥的相关文章

hdu 6390 欧拉函数+容斥(莫比乌斯函数) GuGuFishtion

http://acm.hdu.edu.cn/showproblem.php?pid=6390 题意:求一个式子 题解:看题解,写代码 第一行就看不出来,后面的sigma公式也不会化简.mobius也不会 就自己写了个容斥搞一下(才能维持现在的生活) //别人的题解https://blog.csdn.net/luyehao1/article/details/81672837 #include <iostream> #include <cstdio> #include <cstr

hdu 1695 GCD 欧拉函数+容斥

题意:给定a,b,c,d,k x属于[1 , c],y属于[1 , d],求满足gcd(x,y)=k的对数.其中<x,y>和<y,x>算相同. 思路:不妨设c<d,x<=y.问题可以转化为x属于[1,c / k ],y属于[1,d/k ],x和y互质的对数. 那么假如y<=c/k,那么对数就是y从1到c/k欧拉函数的和.如果y>c/k,就只能从[ c/k+1 , d ]枚举,然后利用容斥.详见代码: /****************************

HDU1695-GCD(数论-欧拉函数-容斥)

GCD Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5454    Accepted Submission(s): 1957 Problem Description Given 5 integers: a, b, c, d, k, you're to find x in a...b, y in c...d that GCD(x, y

HDU 1695 GCD 欧拉函数+容斥定理

输入a b c d k求有多少对x y 使得x在a-b区间 y在c-d区间 gcd(x, y) = k 此外a和c一定是1 由于gcd(x, y) == k 将b和d都除以k 题目转化为1到b/k 和1到d/k 2个区间 如果第一个区间小于第二个区间 讲第二个区间分成2部分来做1-b/k 和 b/k+1-d/k 第一部分对于每一个数i 和他互质的数就是这个数的欧拉函数值 全部数的欧拉函数的和就是答案 第二部分能够用全部数减去不互质的数 对于一个数i 分解因子和他不互质的数包括他的若干个因子 这个

luogu2658 GCD(莫比乌斯反演/欧拉函数)

link 给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的数对(x,y)有多少对. 1<=N<=10^7 (1)莫比乌斯反演法 发现就是YY的GCD,左转YY的GCD粘过来就行 代码太丑,没开O2 TLE5个点 #include <cstdio> #include <functional> using namespace std; const int fuck = 10000000; int prime[10000010], tot; bool v

莫比乌斯反演欧拉函数杜教筛大总结

莫比乌斯函数 定义 设\(n=\prod_{i=1}^{k} p_i^{c_i}\),则\(\mu(n)=(-1)^k\),特别地\(\mu(1)=1\). 性质 最常用性质 \(\sum_{d|n}\mu(d)=[n=1]\) 反演性质 \(F(n)=\sum_{d|n}f(d) \Longleftrightarrow f(n)=\sum_{d|n}F(d)\mu(\frac{n}{d})\) \(F(n)=\sum_{n|d}f(d) \Longleftrightarrow f(n)=\su

HDU 6390 GuGuFishtion(莫比乌斯反演 + 欧拉函数性质 + 积性函数)题解

题意: 给定\(n,m,p\),求 \[ \sum_{a=1}^n\sum_{b=1}^m\frac{\varphi(ab)}{\varphi(a)\varphi(b)}\mod p \] 思路: 由欧拉函数性质可得:\(x,y\)互质则\(\varphi(xy)=\varphi(x)\varphi(y)\):\(p\)是质数则\(\varphi(p^a)=(p-1)^{a-1}\).因此,由上述两条性质,我们可以吧\(a,b\)质因数分解得到 \[ \begin{aligned} \sum_{

HDU1695 GCD (欧拉函数+容斥原理)

求(1,b)区间和(1,d)区间里面gcd(x, y) = k的数的对数(1<=x<=b , 1<= y <= d). b和d分别除以k之后的区间里面,只需要求gcd(x, y) = 1就可以了,这样子求出的数的对数不变. 这道题目还要求1-3 和 3-1 这种情况算成一种,因此只需要限制x<y就可以了 只需要枚举x,然后确定另一个区间里面有多少个y就可以了.因此问题转化成为区间(1, d)里面与x互素的数的个数 先求出x的所有质因数,因此(1,d)区间里面是x的质因数倍数的

BZOJ.2705.[SDOI2012]Longge的问题(莫比乌斯反演 欧拉函数)

题目链接 \(Description\) 求\[\sum_{i=1}^n\gcd(i,n)\] \(Solution\) \[ \begin{aligned} \sum_{i=1}^n\gcd(i,n) &=\sum_{d=1}^nd\sum_{i=1}^n[\gcd(i,n)=d]\ &=\sum_{d=1}^nd\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}[\gcd(i,\lfloor\frac{n}{d}\rfloor)=1] \end{aligned