NJUST 1922 容斥原理

count_prime

Time Limit: 1000ms

Memory Limit: 65536KB


Description

给定你一个数n,请你统计出在[a,b]这个区间中和n互质的数的个数。两个数互质当且仅当他们除了1之外没有其他的公共因子或者他们最大的公共因子是1。1和任何数是互素的。

Input

第一行输入一个整数T(1 <= T <= 100),表示T组测试数据。接下来T行,每行3个整数a,b,n(1 <= a <=b <=10^15, 1<= n <= 10^9),用空格隔开。

Output

输出一个整数表示 和n互质 的数的个数。

Sample Input

2
1 10 2
3 10 5

Sample Output

5
6




 搞了一个多小时,终于弄懂了QAQ,容斥原理。

1-i中,是a的倍数和b的倍数的个数为i/a+i/b-i/(a*b)。
设有n个因子,求 1-i中这n个因子的倍数的个数。
定义变量k,从1开始,for到n,每for一次,任取k个因子相乘,如果是奇数个因子,就把当前值加上i/(k个因子的积),否则减去。


dfs 

cur代表当前的因子,now代表当前的乘积,neg代表奇或偶,mid代表i,res代表结果
f代表元素个数,fac代表因子数组0-(f-1)

void dfs(ll cur,ll now,bool neg,ll mid,ll &res){
	if(cur>=f)return;
	ll num=now*fac[cur]/gcd(now,fac[cur]);//这里是最小公倍数 不然会出错  比如是6或8的倍数且小于等于24  如果不是最小公倍数就会少减一个24
	dfs(cur+1,now,neg,mid,res);//搜不放这个因子的积
	if(neg)res=res+mid/num;
	else res=res-mid/num;
	dfs(cur+1,num,!neg,mid,res);//搜放这个因子的积
} 

#include<iostream>  
#include<stdio.h>  
using namespace std;  
typedef long long ll;  
ll t,n,a,b,i,x,flag,sum,fac[105],f;  
ll gcd(ll a,ll b){
	if(b==0)return a;
	return gcd(b,a%b);
}
void dfs(ll cur,ll now,bool neg,ll mid,ll &res){  
    if(cur>=f)return;  
    ll num=now*fac[cur]/(gcd(now,fac[cur]));  
    dfs(cur+1,now,neg,mid,res);  
    if(neg)res=res+mid/num;  
    else res=res-mid/num;  
    dfs(cur+1,num,!neg,mid,res);  
}  
int main(){  
    cin>>t;  
    while(t--){  
        cin>>a>>b>>n;  
        f=0;  
        ll so=0;  
        for(i=2;n!=1;i++){  
            while(n%i==0){  
                if(so!=i){  
                    fac[f++]=i;  
                }  
                so=i;  
                n/=i;  
            }  
        }  
        ll res=0;  
        dfs(0,1,1,a-1,res);  
        ll so1=a-1-res;  
        res=0;  
        dfs(0,1,1,b,res);  
        ll so2=b-res;  
        cout<<so2-so1<<endl;  
    }  
    return 0;  
}  


 
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值