HDU 4135 Co-prime

来源:互联网 发布:淘宝联盟怎么赚钱的 编辑:程序博客网 时间:2024/06/05 08:24

HDU 4135 Co-prime 传送门

题意

给出一个区间的左右端点,再给出区间里的一个数,然后需要求出在区间中有几个数与给定的数互素。

思路

暴力求解肯定是过不去的,会超时,这里需要利用容斥原理。

假设当前m=12,n=10。

第一步:求出给出数的质因子:2,3,5;

第二步:(1,m)中是n的因子的倍数当然就不互质了(2,4,6,8,10)->n2 6个,(3,6,9,12)->n3 4个,(5,10)->n5 2个。但是所有n的因子当然不是6+4+2=12个,因为其中有算重的,需要在第三步去重。

第三步:利用容斥原理,2,3,5的倍数,减去2和3,3和5,5和2的倍数,再加上2和3和5的倍数。公式就是:

n2+n3+n5n23n35n25+n235

参考代码

#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <algorithm>#include <queue>#include <stack>#include <vector>#include <cmath>#include <set>#include <map>#include <cstdlib>#include <functional>#include <climits>#include <cctype>#include <iomanip>using namespace std;typedef long long ll;#define INF 0x3f3f3f3f#define mod 1e9 + 7#define clr(a, x) memset(a, x, sizeof(a))const double eps = 1e-6;const int MAXN = 10010;ll aprime[MAXN];ll k;void findprime(ll x){    k = 0;    for (int i = 2; i * i <= x; i++)    {        if (x % i == 0)        {            aprime[k++] = i;            while (x % i == 0)                x /= i;        }    }    if (x > 1)        aprime[k++] = x;}ll fun(ll num){    ll que[MAXN], kk, ans = 0, t = 0;    que[t++] = -1;    for (int i = 0; i < k; i++)    {        kk = t;        for (int j = 0; j < kk; j++)        {            que[t++] = aprime[i] * que[j] * (-1);        }    }    for (int i = 1; i < t; i++)    {        ans += (num / que[i]);    }    return ans;}int main(){    int t;    int p = 0;    ll a, b, n;    cin >> t;    while (t--)    {        cin >> a >> b >> n;        findprime(n);        ll ans = (b - fun(b)) - (a - 1 - fun(a - 1));        printf("Case #%d: ", ++p);        cout << ans << endl;    }    return 0;}
原创粉丝点击