1. 程式人生 > >【bzoj2401】陶陶的難題I “高精度”+歐拉函數+線性篩

【bzoj2401】陶陶的難題I “高精度”+歐拉函數+線性篩

== fine 高精度 phi scanf rac 兩個 後乘 線性

題目描述

技術分享

輸入

第一行包含一個正整數T,表示有T組測試數據。接下來T<=10^5
行,每行給出一個正整數N,N<=10^6。

輸出

包含T行,依次給出對應的答案。

樣例輸入

7
1
10
100
1000
10000
100000
1000000

樣例輸出

1
2127
18446224
183011304660
1827127167830060
18269345553999897648
182690854273058293758232


題解

“高精度”+歐拉函數+線性篩

由於$i$和$j$的範圍都是$1$到$n$,因此可以先只計算$j\le i$的情況,然後乘2,再減去多算的$i=1$即為題目中$1$到$n$的情況。

$\ \ \ \ \sum\limits_{i=1}^n\sum\limits_{j=1}^ilcm(i,j)\\=\sum\limits_{i=1}^n\sum\limits_{d|i}\sum\limits_{j=1}^i[gcd(i,j)=d]\frac{ij}d\\=\sum\limits_{i=1}^n\sum\limits_{d|i}\sum\limits_{j=1}^{\frac id}[gcd(\frac id,j)=1]ij\\=\sum\limits_{i=1}^ni\sum\limits_{d|i}\sum\limits_{j=1}^{\frac id}[gcd(\frac id,j)=1]j\\=\sum\limits_{i=1}^ni\sum\limits_{d|i}\sum\limits_{j=1}^{d}[gcd(d,j)=1]j$

而考慮$\sum\limits_{j=1}^d[gcd(d,j)=1]j$的實際含義:$1\sim d$中所有與$d$互質的數的和。考慮當$d>1$時,如果$j$與$d$互質,那麽$d-j$與$d$也一定互質。因此與$d$互質的數一定是成對出現的,每對的和為$d$,故它們的和為$\frac{d\varphi(d)}2$。註意這個公式在$d=1$時不成立,需要特判

於是就有:

$\ \ \ \ \sum\limits_{i=1}^ni\sum\limits_{d|i}\sum\limits_{j=1}^{d}[gcd(d,j)=1]j\\=\frac{\sum\limits_{i=1}^ni(\sum\limits_{d|i}d\varphi(d)+1)}2$

於是所求即為:

$2·\frac{\sum\limits_{i=1}^ni(\sum\limits_{d|i}d\varphi(d)+1)}2-\sum\limits_{i=1}^ni=\sum\limits_{i=1}^ni\sum\limits_{d|i}d\varphi(d)$

(其中很多亂七八糟的東西都消掉了,剩下的式子非常優美)

然後$f(i)=\sum\limits_{d|i}d\varphi(d)$是積性函數,因此可以快篩。

當然,此時$i$與$prime[j]$不互質時沒有很好的通用方法,只好使用快篩的通法:設$n=vp^a$,那麽$f(n)=f(v)*f(p^a)$,此時只需要維護每個數的$p$和$p^a$即可使用等比數列求和公式$O(1)$求出:

$f(p^a)=\frac{p^{2a+1}+1}{p+1}$

然後就可以維護$i·f(i)$的前綴和,然後$O(1)$回答詢問。

然而本題最惡心之處:本題爆long long!因此必須使用中精度,即兩個long long拼起來,每個long long12位。當然,只需要在求前綴和時使用中精度,其它地方long long即可。

時間復雜度$O(n+T)$

#include <cstdio>
#define N 1000010
#define k 1000000
typedef long long ll;
ll f[N] , sx[N] , sy[N];
int w[N] , v[N] , prime[N] , tot , np[N];
int main()
{
	int i , j , t , T , n;
	f[1] = 1;
	for(i = 2 ; i <= k ; i ++ )
	{
		if(!np[i]) w[i] = v[i] = i , f[i] = (ll)i * i - i + 1 , prime[++tot] = i;
		for(j = 1 ; j <= tot && (t = i * prime[j]) <= k ; j ++ )
		{
			np[t] = 1;
			if(i % prime[j] == 0)
			{
				w[t] = w[i] , v[t] = v[i] * w[i] , f[t] = ((ll)v[t] * v[t] * w[t] + 1) / (w[t] + 1) * f[t / v[t]];
				break;
			}
			else w[t] = v[t] = prime[j] , f[t] = f[i] * f[prime[j]];
		}
	}
	for(i = 1 ; i <= k ; i ++ ) sx[i] = sx[i - 1] + i * f[i] , sy[i] = sy[i - 1] + sx[i] / 1000000000000ll , sx[i] %= 1000000000000ll;
	scanf("%d" , &T);
	while(T -- )
	{
		scanf("%d" , &n);
		if(sy[n]) printf("%lld%012lld\n" , sy[n] , sx[n]);
		else printf("%lld\n" , sx[n]);
	}
	return 0;
}

【bzoj2401】陶陶的難題I “高精度”+歐拉函數+線性篩