HDU4135——Co-prime(数论,容斥原理)

来源:互联网 发布:bigworld源码 编辑:程序博客网 时间:2024/05/18 15:27

题目:

Co-prime

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3490    Accepted Submission(s): 1379


Problem Description
Given a number N, you are asked to count the number of integers between A and B inclusive which are relatively prime to N.
Two integers are said to be co-prime or relatively prime if they have no common positive divisors other than 1 or, equivalently, if their greatest common divisor is 1. The number 1 is relatively prime to every integer.
 

Input
The first line on input contains T (0 < T <= 100) the number of test cases, each of the next T lines contains three integers A, B, N where (1 <= A <= B <= 1015) and (1 <=N <= 109).
 

Output
For each test case, print the number of integers between A and B inclusive which are relatively prime to N. Follow the output format below.
 

Sample Input
21 10 23 15 5
 

Sample Output
Case #1: 5Case #2: 10
Hint
In the first test case, the five integers in range [1,10] which are relatively prime to 2 are {1,3,5,7,9}.
 

Source
The Third Lebanese Collegiate Programming Contest
 

题意:求区间[a,b]上与p互质的数字的个数,其中(1 <= a <=b <= 1015) and (1 <=p <= 109)

思路:首先直接求a,b上和p互质的数并不方便。所以考虑分别求[1,a-1],和[1,b]上和p互质的数的个数。它们的差就是答案。

那么如何去求[1,n]上与p互质的数的个数?

这时候就需要用到容斥原理了。以p有三个不同的的质因数为例。设为a,b,c。

那么[1,n]上不和p互质的数的个数为,m=n/a+n/b+n/c-n/(a*b)-n/(a*c)-n/(b*c)+n/(a*b*c)           (奇加偶减)

互质的数的个数就是n-m

计算的时候可以用dfs,队列数组,还有状态压缩。


#include <cmath>#include <cstring>#include <cstdio>#include <vector>#include <string>#include <algorithm>#include <string>#include <iostream>using namespace std;#define MAXN 55#define INF 1e9+7#define MODE 1000000typedef long long ll;int t;ll a,b,n;vector <int>ans;ll solve(ll n){    //que用来保存每一项分母,分母是偶数个相乘为负,奇数个为正    ll que[10000];    int t=0;    que[t++]=-1;    for(int i=0;i<ans.size();i++)    {        int k=t;        for(int j=0;j<k;j++)        {            que[t++]=que[j]*ans[i]*(-1);        }    }    ll sum=0;    for(int i=1;i<t;i++)        sum=sum+n/que[i];    return n-sum;}int main(){    scanf("%d",&t);    for(int cas=1;cas<=t;cas++)    {        scanf("%I64d%I64d%I64d",&a,&b,&n);        ans.clear();        int temp=n;        for(int i=2;i*i<=temp;i++)        {            if(temp%i==0){                ans.push_back(i);                while(temp%i==0)                    temp/=i;            }        }        if(temp>1)            ans.push_back(temp);        ll s1=solve(a-1);        ll s2=solve(b);        printf("Case #%d: %I64d\n",cas,s2-s1);    }}







0 0
原创粉丝点击