【bzoj2749】[HAOI2012]外星人

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Joky_2002/article/details/81411591

题目链接

。。。。。模型转化错了被自己蠢到哭

就首先这题如果说质因数只有 2 的时候,操作次数肯定是 2 的个数
如果质因数不只有 2 的时候
考虑 φ ( i ) 的式子,做一次操作就相当于把每种质因数取一个出来,都减去 1 ,然后再质因数分解回去

由于质数除了 2 都是奇数,所以减 1 再质因数分解肯定会多很多 2 出来
形式化点,如果存在除了 2 以外的质因数,我们做一次操作 多出的 2 的个数 1
而我们每次最多只能删掉 1 2 ,稍加分析就可以得出
答案就是 能分出的 2 的个数 + N 是否为奇数
因为奇数的时候只有第一次操作没有 2 可以消,其余操作每次都有

而“能分出的 2 的个数这个东西”是能线性筛出来的

然后这样就做完了

代码:

#include<cstdio>
#include<vector>
#include<queue>
#include<ctime>
#include<algorithm>
#include<cstdlib>
#include<stack>
#include<cstring>
#include<cmath>
using namespace std;

typedef long long LL;

const int INF = 2147483647;
const int maxn = 100010;

LL ans,f[maxn],pri[maxn],tot;
bool mark[maxn];

inline LL getint()
{
    LL ret = 0,f = 1;
    char c = getchar();
    while (c < '0' || c > '9')
    {
        if (c == '-') f = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') ret = ret * 10 + c - '0',c = getchar();
    return ret * f;
}

int main()
{
    #ifdef AMC
        freopen("AMC1.txt","r",stdin);
    #endif
    f[2] = 1;
    for (int i = 2; i <= 100000; i++)
    {
        if (!mark[i])
            pri[++tot] = i , f[i] = i == 2 ? 1 : f[i - 1];
        for (int j = 1; j <= tot; j++)
        {
            if (i * pri[j] > 100000) break;
            mark[i * pri[j]] = 1;
            f[i * pri[j]] = f[i] + f[pri[j]];
            if (i % pri[j] == 0) break;
        }
    }

    int t = getint();
    while (t--)
    {
        ans = 0;
        int n = getint(),flag = 0;
        for (int i = 1; i <= n; i++)
        {
            LL p = getint(),q = getint();
            ans += f[p] * q;
            flag += !(p & 1);
        }
        if (!flag) ans++;
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Joky_2002/article/details/81411591