HDU-4135 Co-prime(容斥原理模板題)
C - C
Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u
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 <= 10 15) and (1 <=N <= 10 9).
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
2 1 10 2 3 15 5
Sample Output
Case #1: 5 Case #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}.
【題意】
輸入a,b,c求[a , b]範圍中與c互質的數的個數。簡化成 -> [1 , b] 中與c互質的數的個數 - [1 , a) 中與c互質的數的個數
題目化簡成了用兩次 -> 容斥原理簡單應用:求[1 , m]中與n互質的數的個數(btw,這裡不是尤拉函式的應用!!)
套下模板就好了~~
這題我開的...傻兮兮的超時了首wa,被隊友罵死。又是用到容斥原理啦要記住了呀!!!
【簡單容斥原理模板】參考連結
typedef long long ll;
ll solve(ll x,ll n)//計算1~x中 與n互質的數的個數的模板
{
vector<ll> vt;
vt.clear();
ll i,j;
for(i=2;i*i<=n;i++)
if(n%i==0)
{
vt.push_back(i);
while(n%i==0)
n/=i;
}
if(n>1)
vt.push_back(n);
ll sum=0,val,cnt;
for(i=1;i<(1<<vt.size());i++)
{
val=1;
cnt=0;
for(j=0;j<vt.size();j++)
if(i&(1<<j))
{
val*=vt[j];
cnt++;
}
if(cnt&1)
sum+=x/val;
else
sum-=x/val;
}
return x-sum;
}
【通過程式碼】
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <map>
#include <vector>
#include <algorithm>
#include <iostream>
#define go(i,a,b) for(ll i=a;i<=b;i++)
#define mem(a) memset(a,0,sizeof(a))
using namespace std;
const int maxn = 1e6 + 5;
typedef long long ll;
ll solve(ll x,ll n)//計算1~x中 與n互質的數的個數的模板
{
vector<ll> vt;
vt.clear();
ll i,j;
for(i=2;i*i<=n;i++)
if(n%i==0)
{
vt.push_back(i);
while(n%i==0)
n/=i;
}
if(n>1)
vt.push_back(n);
ll sum=0,val,cnt;
for(i=1;i<(1<<vt.size());i++)
{
val=1;
cnt=0;
for(j=0;j<vt.size();j++)
if(i&(1<<j))
{
val*=vt[j];
cnt++;
}
if(cnt&1)
sum+=x/val;
else
sum-=x/val;
}
return x-sum;
}
int main()
{
ll t,a,b,c;
scanf("%lld",&t);
go(i,1,t)
{
scanf("%lld%lld%lld",&a,&b,&c);
printf("Case #%lld: %lld\n",i,solve(b,c) - solve(a - 1,c));
}
return 0;
}