hdu 1695

来源:互联网 发布:装饰工程报价软件 编辑:程序博客网 时间:2024/06/09 22:31

链接:http://http://acm.hdu.edu.cn/showproblem.php?pid=1695

题意:在(a,b)找x,在(c,d)找y,使得gcd(x,y)=k;

   其中a=c=1;

   这样就可理解为x在(1,b/k),y在(1,d/k)且x,y互质

介绍两种方法

第一种容斥定理

还是直接看代码,不解释

#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <set>#include <map>#include <string>#include <math.h>#include <stdlib.h>#include <time.h>using namespace std;const int MAXN = 10000;int prime[MAXN+1];void getPrime(){    memset(prime,0,sizeof(prime));    for(int i = 2;i <= MAXN;i++)    {        if(!prime[i])prime[++prime[0]] = i;        for(int j = 1;j <= prime[0] && prime[j] <= MAXN/i;j++)        {            prime[prime[j]*i] = 1;            if(i%prime[j] == 0)break;        }    }}long long factor[100][2];int fatCnt;int getFactors(long long x){    fatCnt = 0;    long long tmp = x;    for(int i = 1; prime[i] <= tmp/prime[i];i++)    {        factor[fatCnt][1] = 0;        if(tmp%prime[i] == 0)        {            factor[fatCnt][0] = prime[i];            while(tmp%prime[i] == 0)            {                factor[fatCnt][1]++;                tmp /= prime[i];            }            fatCnt++;        }    }    if(tmp != 1)    {        factor[fatCnt][0] = tmp;        factor[fatCnt++][1] = 1;    }    return fatCnt;}int euler[100010];void getEuler(){    memset(euler,0,sizeof(euler));    euler[1] = 1;    for(int i = 2;i <= 100000;i++)        if(!euler[i])            for(int j = i; j <= 100000;j += i)            {                if(!euler[j])                    euler[j] = j;                euler[j] = euler[j]/i*(i-1);            }}int calc(int n,int m)//n < m,求1-n内和m互质的数的个数{    getFactors(m);    int ans = 0;    for(int i = 1;i < (1<<fatCnt);i++)    {        int cnt = 0;        int tmp = 1;        for(int j = 0;j < fatCnt;j++)            if(i&(1<<j))            {                cnt++;                tmp *= factor[j][0];            }        if(cnt&1)ans += n/tmp;        else ans -= n/tmp;    }    return n - ans;}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    getPrime();    int a,b,c,d;    int T;    int k;    scanf("%d",&T);    int iCase = 0;    getEuler();    while(T--)    {        iCase++;        scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);        if(k == 0 || k > b || k > d)        {            printf("Case %d: 0\n",iCase);            continue;        }        if(b > d)swap(b,d);        b /= k;        d /= k;        long long ans = 0;        for(int i = 1;i <= b;i++)            ans += euler[i];        for(int i = b+1;i <= d;i++)            ans += calc(b,i);        printf("Case %d: %I64d\n",iCase,ans);    }    return 0;}

第二种莫比乌斯反演

初学就转载了http://www.cnblogs.com/kuangbin/archive/2013/08/21/3273440.html

#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <set>#include <map>#include <string>#include <math.h>#include <stdlib.h>#include <time.h>using namespace std;const int MAXN = 1000000;bool check[MAXN+10];int prime[MAXN+10];int mu[MAXN+10];void Moblus(){    memset(check,false,sizeof(check));    mu[1] = 1;    int tot = 0;    for(int i = 2; i <= MAXN; i++)    {        if( !check[i] )        {            prime[tot++] = i;            mu[i] = -1;        }        for(int j = 0; j < tot; j++)        {            if(i * prime[j] > MAXN) break;            check[i * prime[j]] = true;            if( i % prime[j] == 0)            {                mu[i * prime[j]] = 0;                break;            }            else            {                mu[i * prime[j]] = -mu[i];            }        }    }}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    int T;    int a,b,c,d,k;    Moblus();    scanf("%d",&T);    int iCase = 0;    while(T--)    {        iCase++;        scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);        if(k == 0)        {            printf("Case %d: 0\n",iCase);            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)mu[i]*(b/i)*(d/i);        long long ans2 = 0;        for(int i = 1;i <= b;i++)            ans2 += (long long)mu[i]*(b/i)*(b/i);        ans1 -= ans2/2;        printf("Case %d: %I64d\n",iCase,ans1);    }    return 0;}


0 0
原创粉丝点击