Comet OJ - Contest #8 E.神奇函數(歐拉函數性質)

題目描述

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

BB

其實是一道sb題
1013+10組數據足以把
杜教篩/min25/洲閣篩/反演+篩μ/分塊+篩質數
給送上天了
所以正解肯定是T√n的做法

性質

歐拉函數有一個著名的性質:
n=dnφ(d)n=\sum_{d|n}{\varphi(d)}
證明:
F(n)=dnφ(d)F(n)=\sum_{d|n}{\varphi(d)},則
F(n)F(m)=inφ(i)jmφ(j)F(n)*F(m)=\sum_{i|n}{\varphi(i)}*\sum_{j|m}{\varphi(j)}(nm互質)
=injmφ(ij)=\sum_{i|n}{\sum_{j|m}{\varphi(i*j)}}
=F(nm)=F(n*m)
所以證得F(n)是積性函數
F(pk)F(p^k)(p爲質數)
F(pk)=i=0kφ(pi)F(p^k)=\sum_{i=0}^{k}{\varphi(p^i)}
=(i=1kpi(11p))+1=(\sum_{i=1}^{k}{p^i*(1-\frac{1}{p})})+1
=(i=1kpi1(p1))+1=(\sum_{i=1}^{k}{p^{i-1}*(p-1)})+1
=(i=1kpipi1)+1=(\sum_{i=1}^{k}{p^i-p^{i-1}})+1
=pkp0+1=p^k-p^0+1
=pk=p^k
由於F(n)是積性函數,且F(pk)=pk,所以可以推得F(n)=n(對於任意n)
所以
F(n)=dnφ(d)F(n)=\sum_{d|n}{\varphi(d)}
n=dnφ(d)n=\sum_{d|n}{\varphi(d)}
參考:https://blog.csdn.net/liuzibujian/article/details/81086324

題解

題目的f(n)=aipi2f(n)=\prod{{a_i}^{\left \lfloor \frac{p_i}{2} \right \rfloor}}
可以發現,每個質因子的質數除了2
那麼
f(n)=df(n)φ(d)f(n)=\sum_{d|f(n)}{\varphi(d)}
本質上,枚舉d其實是枚舉n中指數爲1的倍數的約數
由於先前除了2,考慮把d和f(n)的指數都乘以2,這樣得到的實際上是一樣的
所以
f(n)=d2nφ(d)f(n)=\sum_{d^2|n}{\varphi(d)}
ans=i=1nf(i)=i=1nd2iφ(d)ans=\sum_{i=1}^{n}{f(i)}=\sum_{i=1}^{n}{\sum_{d^2|i}{\varphi(d)}}
=d=1nd2i  and  inφ(d)=\sum_{d=1}^{\left \lfloor \sqrt{n} \right \rfloor}{\sum_{d^2|i \; and \; i\leqslant n}{\varphi(d)}}
=d=1nφ(d)nd2=\sum_{d=1}^{\left \lfloor \sqrt{n} \right \rfloor}{\varphi(d)*\left \lfloor \frac{n}{d^2} \right \rfloor}
沒了

code

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define Len 3162277
using namespace std;

bool f[Len+1];
int p[Len+1];
int phi[Len+1];
int T,N,i,j,k,l,len;
long long n,ans;

void init()
{
	int i,j;
	
	memset(f,0,sizeof(f));
	len=0;
	
	phi[1]=1;
	fo(i,2,Len)
	{
		if (!f[i])
		{
			p[++len]=i;
			phi[i]=i-1;
		}
		
		fo(j,1,len)
		if ((long long)i*p[j]<=Len)
		{
			f[i*p[j]]=1;
			phi[i*p[j]]=phi[i]*p[j];
			
			if (!(i%p[j]))
			break;
			
			phi[i*p[j]]=phi[i*p[j]]/p[j]*(p[j]-1);
		}
		else
		break;
	}
}

int main()
{
//	freopen("e.in","r",stdin);
	
	init();
	
	scanf("%d",&T);
	for (;T;--T)
	{
		scanf("%lld",&n);
		N=floor(sqrt(n));
		
		ans=0;
		fo(i,1,N)
		ans+=phi[i]*(n/i/i);
		
		printf("%lld\n",ans);
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章