1. 程式人生 > >2018ACM-ICPC南京賽區網路賽: J. Sum(積性函式字首和)

2018ACM-ICPC南京賽區網路賽: J. Sum(積性函式字首和)

J. Sum

A square-free integer is an integer which is indivisible by any square number except 11. For example, 6 = 2 \cdot 36=2⋅3 is square-free, but 12 = 2^2 \cdot 312=22⋅3 is not, because 2^222 is a square number. Some integers could be decomposed into product of two square-free integers, there may be more than one decomposition ways. For example, 6 = 1\cdot 6=6 \cdot 1=2\cdot 3=3\cdot 2, n=ab6=1⋅6=6⋅1=2⋅3=3⋅2,n=ab and n=ban=ba are considered different if a \not = ba̸=b. f(n)f(n) is the number of decomposition ways that n=abn=ab such that aa and bb are square-free integers. The problem is calculating \sum_{i = 1}^nf(i)∑i=1n​f(i).

Input

The first line contains an integer T(T\le 20)T(T≤20), denoting the number of test cases.

For each test case, there first line has a integer n(n \le 2\cdot 10^7)n(n≤2⋅107).

Output

For each test case, print the answer \sum_{i = 1}^n f(i)∑i=1n​f(i).

Hint

\sum_{i = 1}^8 f(i)=f(1)+ \cdots +f(8)∑i=18​f(i)=f(1)+⋯+f(8)
=1+2+2+1+2+4+2+0=14=1+2+2+1+2+4+2+0=14.

題意:

令F(i)表示滿足x*y=i,且x和y都不包含平方數因子的合法(x,y)對數,求∑F(i)

思路:

很容易證明F(i)是積性函式,如果i中不存在3次方以上的質因子,F(i) = 2^(i中只出現一次的質因子個數),否則F(i) = 0

那麼就是個積性函式字首和的問題了

很多項都為0,利用Min_25篩可以在1s內輕鬆解決\small 10^{10}範圍內的所有詢問

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<string>
#include<math.h>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
#define LL long long
#define mod 1000000007
#define er 500000004
int cnt, s[200005], id[200005], B, m, h[200005];
bool flag[200005];
LL n, w[200005], pri[200005];
void Primeset(int n)
{
	int i, j;
	for(i=2;i<=n;i++)
	{
		if(flag[i]==0)
		{
			pri[++cnt] = i;
			s[cnt] = s[cnt-1]+i;
		}
		for(j=1;j<=cnt&&i*pri[j]<=n;j++)
		{
			flag[i*pri[j]] = 1;
			if(i%pri[j]==0)
				break;
		}
	}
}
LL F(LL x, int y)
{
	LL t1;
	int i, k, e, ans;
	if(x<=1 || pri[y]>x)
		return 0;
	if(x>B)
		k = n/x;
	if(x<=B)
		k = id[x];
	ans = 2*(h[k]-(y-1));
	for(i=y;i<=cnt&&(LL)pri[i]*pri[i]<=x;i++)
	{
		t1 = pri[i];
		for(e=1;t1*pri[i]<=x;e++)
		{
			if(e==1)
				ans = (ans+(F(x/t1, i+1)*2+1));
			else if(e==2)
				ans = (ans+F(x/t1, i+1));
			t1 *= pri[i];
		}
	}
	return ans;
}

int main(void)
{
	LL i, j, k, last;
	int T;
	scanf("%d", &T);
	while(T--)
	{
		m = cnt = 0;
		scanf("%lld", &n);
		B = sqrt(n), Primeset(B);
		for(i=1;i<=n;i=last+1)
		{
			w[++m] = n/i;
			h[m] = w[m]-1;
			last = n/(n/i);
			if(n/i<=B)
				id[n/i] = m;
		}
		for(j=1;j<=cnt;j++)
		{
			for(i=1;i<=m&&pri[j]*pri[j]<=w[i];i++)
			{
				if(w[i]/pri[j]<=B)
					k = id[w[i]/pri[j]];
				else
					k = n/(w[i]/pri[j]);
				h[i] = h[i]-(h[k]-(j-1));
			}
		}
		printf("%lld\n", (F(n, 1)+1));
	}
	return 0;
}