• hdu-1695 GCD---容斥定理


    题目链接:

    http://acm.hdu.edu.cn/showproblem.php?pid=1695

    题目大意:

    求解区间[1, n]和[1, m]中有多少对不同的x和y使得gcd(x, y) == k

    其中x=5 y=7和x=7 y=5是同一对

    解题思路:

    首先如果gcd为k说明[1, n]中只有k的倍数为x,同理在[1, m]中也只有k的倍数为y。

    所以如果先特判,k=0或者k>n或者k>m都是不存在解的情况。

    之后n /= k, m /= k,这是之选出k的倍数,作为x和y,并且gcd(x, y) = k,就是等价于求在现在的1-n区间和1-m区间中求互质对数。

    还需考虑重复的情况,所以枚举m的时候求区间[m, n]与m互质的数,这样不会重复枚举。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int maxn = 1e6 + 10;
     5 ll a[50], tot;
     6 ll gcd(ll a, ll b)
     7 {
     8     return b == 0 ? a : gcd(b, a % b);
     9 }
    10 void init(ll n)//求出n的素因子
    11 {
    12     tot = 0;
    13     for(ll i = 2; i * i <= n; i++)
    14     {
    15         if(n % i == 0)
    16         {
    17             a[tot++] = i;
    18             while(n % i == 0)n /= i;
    19         }
    20     }
    21     if(n != 1)a[tot++] = n;
    22 }
    23 ll sum(ll m)//求[1, m]中与n互质的个数
    24 {
    25     ll ans = 0;
    26     for(int i = 1; i < (1 << tot); i++)//a数组的子集
    27     {
    28         ll num = 0;
    29         for(int j = i; j; j >>= 1)if(j & 1)num++;//统计i的二进制中1的个数
    30         ll lcm = 1;
    31         for(int j = 0; j < tot; j++)
    32             if((1 << j) & i)
    33         {
    34             lcm = lcm / gcd(lcm, a[j]) * a[j];
    35             if(lcm > m)break;
    36         }
    37         if(num & 1)ans += m / lcm;//奇数加上
    38         else ans -= m / lcm;//偶数减去
    39     }
    40     return m - ans;
    41 }
    42 int main()
    43 {
    44     int T, cases = 0, a, b, n, m, k;
    45     cin >> T;
    46     while(T--)
    47     {
    48         ll ans;
    49         scanf("%d%d%d%d%d", &a, &n, &b, &m, &k);
    50         if(k == 0 || n < k || m < k)ans = 0;
    51         else
    52         {
    53             n /= k, m /= k;
    54             if(n < m)swap(n, m);
    55             ans = n;
    56             for(int i = 2; i <= m; i++)
    57             {
    58                 init(i);
    59                 //cout<<ans<<endl;
    60                 ans += sum(n) - sum(i - 1);
    61             }
    62         }
    63         cout<<"Case "<<++cases<<": "<<ans<<endl;
    64     }
    65     return 0;
    66 }
  • 相关阅读:
    2018级 面向对象程序设计 助教总结
    十二,时间序列趋势相似性度量方法的研究-DPM
    第十八周博客作业
    LSTM与BiLSTM
    基于自训练的半监督文本分类算法
    随机游走模型
    PMI点互信息
    Transductive Learning(直推式学习)
    TextCNN实验
    TextCNN
  • 原文地址:https://www.cnblogs.com/fzl194/p/9085868.html
Copyright © 2020-2023  润新知