2749: [HAOI2012]外星人
Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 707 Solved: 378
[ Submit][ Status][ Discuss]
Description
Input
Output
输出test行,每行一个整数,表示答案。
Sample Input
1
2
2 2
3 1
2
2 2
3 1
Sample Output
3
HINT
Test<=50 Pi<=10^5,1<=Q1<=10^9
Source
并不会写。。。。智商太低了
首先,,利用定义式分解n,把每个(pi - 1)再质因数分解,这样就可以再用定义式分解了
如果pi是个奇数的话,(pi - 1)一定含有质因数2,而且,2是唯一一个偶数质数
那么得出结论,答案就是不断分解过程中2的累计次数和。
因为任意2^k用上述式子,一定要φ^k(2^k) == 1。而且其它质数在分解过程中的出现次数肯定不超过2的次数
发现了这个剩下就好解决了。。。。。
定义f[i]:分解i的过程中2的出现次数。因为幂次这个东西是可以叠加的,所以处理并不难
f[i*pri[j]] = f[i] + f[pri[j]] f[pri[j]] = f[pri[j] - 1],线性筛出来就行了
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<bitset>
using namespace std;
const int maxn = 1E5 + 10;
typedef long long LL;
int T,tot,pri[maxn];
LL f[maxn];
bool not_pri[maxn];
int getint()
{
char ch = getchar(); int ret = 0;
while (ch < '0' || '9' < ch) ch = getchar();
while ('0' <= ch && ch <= '9')
ret = ret*10 + ch - '0',ch = getchar();
return ret;
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
f[1] = 1;
for (int i = 2; i < maxn; i++)
{
if (!not_pri[i])
{
pri[++tot] = i;
f[i] = f[i-1];
}
for (int j = 1; j <= tot; j++)
{
int Nex = pri[j]*i;
if (Nex >= maxn) break;
not_pri[Nex] = 1;
f[Nex] = f[i] + f[pri[j]];
if (i % pri[j] == 0) break;
}
}
T = getint();
while (T--)
{
int n = getint(),Add = 1;
LL Ans = 0;
while (n--)
{
int p = getint(),q = getint();
if (p == 2) Add = 0;
Ans += 1LL*q*f[p];
}
printf("%lld\n",Ans + 1LL*Add);
}
return 0;
}