题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4135
容斥定理求一个区间内与n互素的数有几个;
和模板差不多,只是区间 [1,R] 变成 [L,R],所以可以求出 [1,L] 和 [1,R] 的互素的数的shu'lian再相减,注意这道题的范围;
关于容斥定理的详解 我推荐这篇博客:https://blog.csdn.net/m0_37286282/article/details/78869512#t6)
先给出模板:
int solve (int n, int r)
{
vector<int> p;
for (int i=2; i*i<=n; ++i)
if (n % i == 0)
{
p.push_back (i);
while (n % i == 0)
n /= i;
}
if (n > 1)
p.push_back (n);
int sum = 0;
for (int msk=1; msk<(1<<p.size()); ++msk)
{
int mult = 1,
bits = 0;
for (int i=0; i<(int)p.size(); ++i)
if (msk & (1<<i))
{
++bits;
mult *= p[i];
}
int cur = r / mult;
if (bits % 2 == 1)
sum += cur;
else
sum -= cur;
}
return r - sum;
}
这是AC代码:
#include<stdio.h>
#include<string.h>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<set>
#include<algorithm>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N=1e5+10;
vector<ll>p;
ll solve(ll l,ll r,ll n)
{
p.clear();
for(ll i=2;i*i<=n;i++)
{
if(n%i==0)
{
p.push_back(i);
while(n%i==0)
n/=i;
}
}
if(n>1)
p.push_back(n);
ll suma=0,sumb=0;
for(int i=1;i<(1<<p.size());++i)
{
ll k=0;
ll pa=1,pb=1;
for(int j=0;j<p.size();++j)
{
if(i&(1<<j))
{
k++;
pa*=p[j];
pb*=p[j];
}
}
pa=l/pa;
pb=r/pb;
if(k%2==1)
suma+=pa,sumb+=pb;
else
suma-=pa,sumb-=pb;
}
return sumb-suma;
}
int main()
{
int T,cal=0;
scanf("%d",&T);
while(T--)
{
ll l,r,n;
scanf("%lld %lld %lld",&l,&r,&n);
l--;
printf("Case #%d: %lld\n",++cal,r-l-solve(l,r,n));
}
return 0;
}