ACM-ICPC 2018南京赛区网络预赛 J.Sum
Problem Description
A square-free integer is an integer which is indivisible by any square number except 1. For example, 6 = 2 ·3,6=2⋅3 is square-free, but 12 = 2^2 · 3, not, because 2^2
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⋅6=6⋅1=2⋅3=3⋅2,n=a·b and n=b·a,n=b·a are considered different if a != b. f(n) is the number of decomposition ways that n=a·bsuch that a and b are square-free integers. The problem is calculating ∑ i=1 n f(i). //f(i),从1到N的和
Input
The first line contains an integer T(T≤20), denoting the number of test cases.
For each test case, there first line has a integer n(2<=n≤2⋅10 ^7).
Output
For each test case, print the answer \sum_{i = 1}^n f(i)∑ i=1 n f(i).
Hint
\sum_{i = 1}^8 f(i)=f(1)+ \cdots +f(8)∑
i=1 8
f(i)=f(1)+⋯+f(8)
=1+2+2+1+2+4+2+0=14=1+2+2+1+2+4+2+0=14.
样例输入
2
5
8
样例输出
8
14
题目来源
ACM-ICPC 2018 南京赛区网络预赛
题意
题目是直接复制粘贴的,结果一些地方符号显示不正常,不会改QAQ,抱歉
T组输入,每次询问一个整数N,求从1到N的 f ( i ) 的和 (N>=2)
f ( X )是一个函数,其值为满足X=a*b的方案书,a, b的顺序不同认为是两种方案
且 a 和 b 不能是除 1 外其他平方数的倍数
如 8 是 平方数 4 的倍数,所以 8 不能作为 a 或者 b
思路
显然,对于一个素数prime ,f(prime)=2,因为有prime = 1 * prime,prime=prime * 1 两种方案
而对于 X= prime1 * prime2,f(X) =4,因为有X=1 * X,X= X * 1,
X=prime1 * prime2, X=prime2 * prime1
同理如X是有三不同个素数的乘积,则 f(X)= 8
这样就可以知道 f ( m+1个不同素数的乘积 ) = 2 * f ( m个不同素数的乘积)
且 f (一个素数) = 2
上面分析的是一种情况
下面分析对于其他整数
很明显 对于 X = K * m^3 //一个数是某个数的三次方的整数倍
因为要把 X 分成两个数a,b的乘积,无论怎么分,至少会有一个 a 或 b 是 m^2 的倍数
比如:
k, m^3、m^3,k
m, km^2、 km^2, m
km, m^2、 m^2, k
可见上面的6种组合方式 a, b 总有一个数是平方数 m^2 的倍数,不能满足题意
故 f (>=3个相同素数的倍数) = 0
另外 特别地对于一个素数 m 而言 , f ( m^2 )=1,m^2 = m*m
因为N较大,所以可以用类似欧拉筛的方法打表
AC代码
#include <bits/stdc++.h>
#define maxlen 1e15
using namespace std;
const int maxn=2e7+10;
typedef long long ll;
ll ans[maxn],a[maxn]; //ans存答案,a[i],存整数 i 的方案数
int prime[maxn]; //存素数
bool vis[maxn];
void init()
{
memset(vis,0,sizeof(vis)); //初始化
int cnt=0;
a[1]=1; //初始化
int i,j;
for(i=2;i<maxn;i++){
if(!vis[i]){
prime[++cnt]=i;
a[i]=2; //对于单个素数,方案数显然为 2
}
for(j=1;j<=cnt&&i*prime[j]<maxn;j++){
vis[i*prime[j]]=true;
if(i%prime[j]==0){
if(i%(prime[j]*prime[j])==0){
a[i*prime[j]]=0; //K*m^3的情况
}
else a[i*prime[j]]=a[i]/2; //相当于少一个素数的情况,因为两个相同素数必须要分开
break;
}
else{
a[i*prime[j]]=a[i]*2; //多一个不同素数的乘积
}
}
}
ans[0]=0;
ans[1]=0;
for(i=1;i<maxn;i++){
ans[i]=ans[i-1]+a[i]; //累加
}
}
int main()
{
init();
int t;
scanf("%d", &t);
while(t--){
int n;
scanf("%d", &n);
printf("%lld\n",ans[n]);
}
return 0;
}