程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> HDU 1695 GCD 歐拉函數+容斥原理

HDU 1695 GCD 歐拉函數+容斥原理

編輯:C++入門知識

從1-b和1-d中各取一個數,使得其最大公約數為k。問有多少對。
因為是最大公約數k,所以不僅僅是擁有因子k。除了因子k之外是互質的。
轉化成從1---b/k和1---d/k中取出互質的數對。
從一個區間裡取出一個數,比他小的互質的部分可以通過歐拉函數搞定,另外一部分通過容斥原理實現。
[cpp] 
#include<iostream> 
#include<cstdio> 
#include<cstring> 
#include<queue> 
#include<vector> 
#include<cmath> 
#define LL  long long 
#define MOD 1000000007 
#define eps 1e-6 
#define N 100010 
#define zero(a)  fabs(a)<eps 
using namespace std; 
LL eular[N]; 
int prime[N][15],cnt[N]; 
void Prime(){ 
    for(int i=2;i<N;i++){ 
        if(eular[i]==i){ 
            eular[i]=i-1; 
            for(int j=2;j*i<N;j++){ 
                eular[i*j]=eular[i*j]*(i-1)/i; 
                prime[j*i][cnt[j*i]++]=i; 
            } 
        } 
        eular[i]+=eular[i-1]; 
    } 

void Init(){ 
    for(int i=1;i<N;i++) 
        eular[i]=i; 
    memset(cnt,0,sizeof(cnt)); 
    Prime(); 

LL dfs(int idx,int cur,int now){ 
    LL ret=0; 
    for(int i=idx;i<cnt[now];i++) 
        ret+=cur/prime[now][i]-dfs(i+1,cur/prime[now][i],now); 
    return ret; 

int main(){ 
    int t,cas=0; 
    Init(); 
    scanf("%d",&t); 
    while(t--){ 
        int a,b,c,d,k,l,r; 
        scanf("%d%d%d%d%d",&a,&b,&c,&d,&k); 
        if(k==0){ 
            printf("Case %d: 0\n",++cas); 
            continue; 
        } 
        l=b/k; 
        r=d/k; 
        if(l>r) 
            swap(l,r); 
        //1-l通過歐拉函數求出 
        LL ans=eular[l]; 
        //1-l中與i互質的數 
        for(int i=l+1;i<=r;i++) 
            ans+=l-dfs(0,l,i); 
        printf("Case %d: %I64d\n",++cas,ans); 
    } 
    return 0; 

作者:ACM_cxlove

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved