程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> hdu 1695 綜合數論 歐拉函數 分解質因子 容斥原理 打印素數表 帥呆了的一個題目 詳解

hdu 1695 綜合數論 歐拉函數 分解質因子 容斥原理 打印素數表 帥呆了的一個題目 詳解

編輯:C++入門知識

GCD
Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3112    Accepted Submission(s): 1095


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) = k. GCD(x, y) means the greatest common divisor of x and y. Since the number of choices may be very large, you're only required to output the total number of different number pairs.
Please notice that, (x=5, y=7) and (x=7, y=5) are considered to be the same.

Yoiu can assume that a = c = 1 in all test cases.
 

Input
The input consists of several test cases. The first line of the input is the number of the cases. There are no more than 3,000 cases.
Each case contains five integers: a, b, c, d, k, 0 < a <= b <= 100,000, 0 < c <= d <= 100,000, 0 <= k <= 100,000, as described above.
 

Output
For each test case, print the number of choices. Use the format in the example.
 

Sample Input
2
1 3 1 5 1
1 11014 1 14409 9
 

Sample Output
Case 1: 9
Case 2: 736427

Hint
For the first sample input, all the 9 pairs of numbers are (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 5), (3, 4), (3, 5).
 
 

Source
2008 “Sunline Cup” National Invitational Contest
 

Recommend
wangye
[cpp] view plaincopy
/*
題目大意:
 
給你a, b, c, d, k; 找出這樣的一隊 x, y, 使得 gcd(x , y) = k, 並且x ∈[1, b], y ∈ [1, d], 問有多少對符合要求的(x, y)。
 
------------------------------------------------------------------------------
 
 
思路: gcd(x, y) == k 說明x,y都能被k整除, 但是能被k整除的未必gcd=k , 必須還要滿足互質關系. 問題就轉化為了求1~a/k 和 1~b/k間互質對數的問題可以把a設置為小的那個數,
那麼以y>x來保持唯一性(題目要求, 比如[1,3] =[3,1] )
 
接下來份兩種情況:
 
1. y <= a , 那麼對數就是 1~a的歐拉函數的累計和(容易想到)
 
2. y >= a , 這個時候歐拉函數不能用了,怎麼做?  可以用容斥原理,把y與1~a互質對數問題轉換為y的質數因子在1~a范圍內能整除的個數(質數分解和容斥關系),
 
*/ 
 
#include <iostream> 
#include <stdio.h> 
#include <memory.h> 
#include<math.h> 
#include <vector> 
using namespace std; 
 
const int N = 100005; 
typedef long long LL; 
#define maxn 100005 
LL phi[N]; 
vector<LL> link[N]; 
int vis[1000000+5],c;   
LL prime[79000];   
void get_prime()  //打印素數表模板 
{   
    int i,j,n,m;   
    c=0;   
    n=1000000;   
    m=(int)sqrt(n+0.5);   
    memset(vis,0,sizeof(vis));   
    for(i=2;i<=m;i++)    
        if(!vis[i])   
        {   
            for(j=i*i;j<=n;j+=i)   
                vis[j]=1;   
        }   
    for(i=2;i<=n;i++) if(!vis[i])   
        prime[c++]=i;   
}   
 
 
void get_PHI()  //模板  得到1->n之內 與n互質的數的個數  存入phi[n] 
{   
    int i,j;   
    for (i = 1; i <= maxn; i++) phi[i] = i;   
    for (i = 2; i <= maxn; i += 2) phi[i] /= 2;   
    for (i = 3; i <= maxn; i += 2) if(phi[i] == i)   
    {   
        for (j = i; j <= maxn; j += i)   
            phi[j] = phi[j] / i * (i - 1);   
    }   

 
void init()     //求每一個數的質因數,vector儲存   

    LL i, j, k; 
    for(i = 1; i < N; i++)//求n的質因數  也是模板 
    { 
        k = i; 
        for(j = 0; prime[j]*prime[j] <= k; j++) 
        { 
            if(k%prime[j] == 0) 
            { 
                link[i].push_back(prime[j]); 
                while(k%prime[j] == 0) 
                    k /= prime[j]; 
            } 
            if(k == 1) break; 
        } 
        if(k > 1) link[i].push_back(k); 
    } 

 
LL make_ans(LL num,LL n)//1到num中的所有數與n的m個質因子不互質的數的個數 注意是不互質哦    容斥原理 
{   
    LL ans=0,tmp,i,j,flag;   
    for(i=1;i<(LL)(1<<link[n].size());i++)   
    { //用二進制來1,0來表示第幾個素因子是否被用到,如m=3,三個因子是2,3,5,則i=3時二進制是011,表示第2、3個因子被用到     
        tmp=1,flag=0;   
        for(j=0;j<link[n].size();j++)    
            if(i&((LL)(1<<j)))//判斷第幾個因子目前被用到    
                flag++,tmp*=link[n][j];//第j個質因子link[n][j] 
        if(flag&1)//容斥原理,奇加偶減     
            ans+=num/tmp;   
        else   
            ans-=num/tmp;   
    }   
    return ans;   
}   
 
 
int main() 

    LL i, a, b, c, d, k, sum, t, zz = 1;//longlong型的數據 可以用%I64d 來輸入輸出 
    get_prime(); 
    get_PHI(); 
    init(); 
    scanf("%I64d", &t); 
    while(t--) 
    { 
        scanf("%I64d %I64d %I64d %I64d %I64d", &a, &b, &c, &d, &k); 
        if(k == 0 || k > b || k > d) 
        { 
            printf("Case %I64d: 0\n", zz++); 
            continue; 
        } 
        if(b > d) swap(b, d);//保持d較大 
        b /= k; 
        d /= k; 
        sum = 0; 
        for(i = 1; i <= b; i++) 
        { 
            sum += phi[i]; 
        } 
        for(i = b+1; i <= d; i++) 
        { 
            sum += b - make_ans(b, i); 
        } 
        printf("Case %I64d: %I64d\n", zz++, sum); 
    } 
 
    return 0; 

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