HDOJ-1695 GCD

给两个值r, n(r <= n)求1到r中与n互质的数.用容斥原理, 假如n的素因子小于等于r的有p1, p2, p3.那么在1到r中与n互质的数的个数 = r - r / p1 - r / p2 - r / p3 + r / (p1 p2 ) + r / (p1 p3) + r / (p2 * p3) - r / (p1 * p2 * p3).这里采用了二进制枚举.

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <cstdio>
#include <queue>
#define INF 1e9
#define maxn 10000

using namespace std;
typedef long long ll;
ll solve(int r, int n){

    vector<int> v;
    int p = n;
    for(int i = 2; i * i <= p && i <= r; i++){

        if(p % i == 0){
            v.push_back(i);
            while(p % i == 0)
              p /= i;
        } 
    } 
    if(p > 1 && p <= r)
      v.push_back(p);

    ll sum = 0, h = 1 << v.size();
    for(ll i = 1; i < h; i++){

        ll cnt = 0, k = 1;
        for(ll j = 0; (1<<j) <= i; j++){
            if((1<<j) & i){
                k *= v[j];
                cnt++;
            }
        }
        if(cnt&1)
           sum -= r / k;
        else
          sum += r / k;
    } 
    return r + sum;
}
int main(){

//  freopen("in.txt", "r", stdin);
    int t, cas = 0;

    cin >> t;
    while(t--){

        int a, b, c, d, k;
        ll sum = 0;

        scanf("%d%d%d%d%d", &a, &b, &c, &d, &k);
        if(k == 0 || b < k || d < k){
            printf("Case %d: %d\n", ++cas, 0);
            continue;
        } 
        int k1 = b / k;
        int k2 = d / k;
        if(k1 > k2)
          swap(k1, k2);
        for(int i = 1; i <= k2; i++){

            if(i <= k1)
              sum += solve(i, i);
            else
              sum += solve(k1, i);
        }
        printf("Case %d: %lld\n", ++cas, sum);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值