ACM-ICPC 2018南京赛区网络预赛 J.Sum

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值