题目:
题意:
一个数的square-free是它的所有因子中不包含有平方数因子分解的个数(1除外),例如:12可以分解为 4 * 3,但4是平方数,所以f(12) 中就不包括3和4,题意要求。
题解:
对于一个数n,我们可以先分解它的质因子,然后考虑将所有质因子分成两组,考察有多少种不同的分组方式,比如:30 有2,3,5的质因子各一个,那么可以分成(1,30),(2,15),(3,10),(5,6),则 f(30) = 8;设n = a1^p1 + a2^p2 + ...... + ai^pi(ai为质数)。
1)如果有一个pi > 3,那么 f(n) = 0,无论怎么分组,根据鸽巢原理,至少有两个在一边,不符合题意。
2)如果pi =2,ai这两个质因子一定是一边一个。
3)所有pi = 1;那么f(n) = 2^(质因子的个数),可以用组合数来证明:分组时左边可以选0个,右边n个,左边1个,右边n-1个.....,左边+右边也就是 ;
代码:
#include<iostream>
#include<string.h>
using namespace std;
const int maxn = 2e7+7;
int phi[maxn]; //记录每一个数的f[n]
int prime[maxn];
bool vis[maxn];
void Eular() //欧拉筛模板
{
memset(vis,true,sizeof(vis));
phi[1]=1;
int p=0;
for(int i=2;i<maxn;i++)
{
if(vis[i])
{
phi[i]=2; //质数只有两个因子,且不含平方数
prime[p++]=i;
}
for(int j=0;j<p&&i*prime[j]<maxn;j++)
{
int tep = i*prime[j];
vis[tep] = false;
if(i%prime[j]) //i和prime[j]互质,相当于tep多了一个质因子prime[j]
phi[tep]=phi[i]*2;
else if(i%(prime[j]*prime[j])==0) //i含有2个prime[j],则tep含有3个
phi[tep] = 0;
else
{
phi[tep]=phi[i]/2; //tep中有两个prime[j],好比2,3,5多了一个2,模拟一下就知道phi[i]的分组重复了一遍
break;
}
}
}
}
int main()
{
int t,n;
Eular();
for(int i=2;i<maxn-1;i++)
phi[i]+=phi[i-1];
while(cin>>t)
{
while(t--)
{
cin>>n;
cout<<phi[n]<<endl;
}
}
return 0;
}