码迷,mamicode.com
首页 > 其他好文 > 详细

组合 数论 莫比乌斯反演 hdu1695

时间:2018-08-11 22:03:50      阅读:126      评论:0      收藏:0      [点我收藏+]

标签:class   min   void   lld   pen   stream   pac   +=   范围   

题解:https://blog.csdn.net/lixuepeng_001/article/details/50577932

题意:给定范围1-b和1-d求(i,j)=k的数对的数量

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<cstring>
using namespace std;
 
const int MAXN = 1000000;
bool check[MAXN+10];
long long mu[MAXN+10];
long long a,b,c,d,k;
const int N = 1e6 + 5;
long long mob[N], vis[N], prime[N];
int tot;//用来记录prime的个数
 
void Mobius(int n){   //求得莫比乌斯函数值
    memset(prime,0,sizeof(prime));
    memset(mob,0,sizeof(mob));
    memset(vis,0,sizeof(vis));
    tot = 0, mob[1] = 1;
    for(int i = 2; i <=n; i ++){
        if(!vis[i]){
            prime[tot++] = i;
            mob[i] = -1;
        }
        for(int j = 0; j < tot && i * prime[j] <=n ; j ++){
            vis[i * prime[j]] = 1;
            if(i % prime[j]) mob[i * prime[j]] = -mob[i];
            else{
                mob[i * prime[j]] = 0;
                break;
            }
        }
    }
}

int main()
{
    int T;
    Mobius(N); 
    cin>>T;
    int Case=0;
    while(T--)
    {
        cin>>a>>b>>c>>d>>k; 
        cout<<"Case "<<++Case<<": ";      
        if(k==0){
            cout<<"0"<<endl;
            continue;
        }
        b=b/k;
        d=d/k;
        long long ans1=0;
        long long ans=0;
        for(long long i=1;i<=min(b,d);i++)
        {
            ans+=mob[i]*(b/i)*(d/i);
            ans1+=mob[i]*((min(b,d)/i)*(min(b,d)/i));
        }
        printf("%lld\n",ans-(ans1/2));
    }
}

 

组合 数论 莫比乌斯反演 hdu1695

标签:class   min   void   lld   pen   stream   pac   +=   范围   

原文地址:https://www.cnblogs.com/witRY/p/9461083.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!