ACM学习历程—广东工业大学2016校赛决赛-网络赛F 我是好人4(数论)

题目链接:http://gdutcode.sinaapp.com/problem.php?cid=1031&pid=5

这个题目一看就是一道数论题,应该考虑使用容斥原理,这里对lcm进行容斥。

不过直接上去是T,考虑到序列中同时存在iki的话,其实只需要考虑i,所以先对序列中为倍数的对进行处理。

这里的容斥用了hqw的写法。

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <string>
#define LL long long

using namespace std;

const LL maxN = 1e9;
int n;
int t[60], a[60], len;
LL ans;

void input()
{
    scanf("%d", &n);
    len = n;
    for (int i = 0; i < len; ++i)
        scanf("%d", &t[i]);
    for (int i = 0; i < len; ++i)
    {
        if (t[i] == -1) continue;
        for (int j = 0; j < len; ++j)
        {
            if (i == j) continue;
            if (t[j] == -1) continue;
            if (t[j]%t[i] == 0) t[j] = -1;
        }
    }
    int top = 0;
    for (int i = 0; i < len; ++i)
        if (t[i] != -1)
            a[top++] = t[i];
    len = top;
    sort(a, a+len);
}

LL gcd(LL x, LL y)
{
    LL r;
    while (y != 0)
    {
        r = y;
        y = x%y;
        x = r;
    }
    return x;
}

LL lcm(LL x, LL y)
{
    return x/gcd(x, y)*y;
}

void dfs(int now, LL num, int sz)
{
    if (now == len)
    {
        if (sz)
        {
            LL last = maxN/num;
            if (sz&1) ans -= last;
            else ans += last;
        }
        return;
    }
    if (num%a[now] == 0) return;
    dfs(now+1, num, sz);
    LL t = lcm(num, a[now]);
    if (t <= maxN) dfs(now+1, t, sz+1);
}

void work()
{
    if (len == 1 && a[0] == 1) printf("0
");
    else
    {
        ans = maxN;
        dfs(0, 1, 0);
        cout << ans << endl;
    }
}

int main()
{
    //freopen("test.in", "r", stdin);
    int T;
    scanf("%d", &T);
    for (int times = 1; times <= T; ++times)
    {
        input();
        work();
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/andyqsmart/p/5375266.html