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

本文探讨了一种算法,用于解决整数n的无平方因子分解方式的数量问题,并通过筛选法预先计算特定范围内的所有可能情况,以实现快速查询。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

J. Sum

A square-free integer is an integer which is indivisible by any square number except 11. For example, 6 = 2 \cdot 36=2⋅3 is square-free, but 12 = 2^2 \cdot 312=22⋅3 is not, because 2^222 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\cdot 6=6 \cdot 1=2\cdot 3=3\cdot 2, n=ab6=1⋅6=6⋅1=2⋅3=3⋅2,n=ab and n=ban=ba are considered different if a \not = ba̸=b. f(n)f(n) is the number of decomposition ways that n=abn=ab such that aa and bb are square-free integers. The problem is calculating \sum_{i = 1}^nf(i)∑i=1n​f(i).

Input

The first line contains an integer T(T\le 20)T(T≤20), denoting the number of test cases.

For each test case, there first line has a integer n(n \le 2\cdot 10^7)n(n≤2⋅107).

Output

For each test case, print the answer \sum_{i = 1}^n f(i)∑i=1n​f(i).

Hint

\sum_{i = 1}^8 f(i)=f(1)+ \cdots +f(8)∑i=18​f(i)=f(1)+⋯+f(8)
=1+2+2+1+2+4+2+0=14=1+2+2+1+2+4+2+0=14.

题意:

令F(i)表示满足x*y=i,且x和y都不包含平方数因子的合法(x,y)对数,求∑F(i)

思路:

容易发现∑F(i) n > 0等价于(非质数的平凡的倍数 )相乘小于或等于n的方案。 比如对于当n = 8,等价于1,2,3,5,6,7这六个数两两相乘并且相乘结果小于8的种类的个数 ,比如1 * 1 , 1 * 2 , 1 * 3 , 1 * 5 , 1 * 6, 1 * 7 , 2 * 1 , 2 * 2 , 2 * 3 , 3 * 1 , 3 * 2 , 5 * 1 , 6 * 1 , 7 * 1 。共14种。

于是我们可以筛掉质数的平方的倍数,再求非质数的平方的倍数的前缀和(学长说时间复杂度是o(n)的),又因为1 * 2 和2 * 1 等价,所以后面可以优化下变成 O(2n + t * sqrt(n)),又因为题目的t很小,所以方法可行。

#include <iostream> 
#include <cstdio> 
#include <fstream> 
#include <algorithm> 
#include <cmath> 
#include <deque> 
#include <vector> 
#include <queue> 
#include <string> 
#include <cstring> 
#include <map> 
#include <stack> 
#include <set> 
int ans[20000009];
bool tmp[20000009];
const int MAXN=5009;
bool flag[MAXN];
int primes[MAXN/3],pi;
void prime() {
	int i,j;
	pi=0;
	memset(flag,false,sizeof(flag));
	for(i=2; i<MAXN; i++) {
		if(!flag[i]) primes[pi++]=i;
		for(j=0; (j < pi) && (i*primes[j] < MAXN); j++) {
			flag[i * primes[j]] = true;
			if(i % primes[j]==0) break;//保证非素数只筛一次
		}
	}
}
int main() {
	prime();
	for(int i = 2;i < 5000;i++){
		if(flag[i] == false){//如果他是质数,筛掉其平方的倍数 
			for(int j = i * i;j <= 20000000;j += i * i){
				tmp[j] = true;
			}
		}
	}
	ans[0] = 0;
	for(int i = 1;i < 20000009;i++){//求前缀和 
		ans[i] = ans[i - 1];
		if(tmp[i] == false){
			ans[i]++;
		}
	}
//	for(int i = 1;i < 50;i++){
//		printf("%d ",ans[i]);
//	}
	int t,n;
	scanf("%d",&t);
	while(t--){
		long long answer = 0;
		scanf("%d",&n);
		for(int i = 1;i <= n / i;i++){
			if(tmp[i] != true){
				answer += (ans[n / i] - ans[i]) * 2 + 1;
			}
		}
		printf("%lld\n",answer);
	}
}

 

### 关于ACM-ICPC新疆赛区历年真题的获取 对于希望获取ACM-ICPC新疆赛区历年真题的需求,可以通过以下途径实现: #### 资源推荐 1. **GitCode 开源工具箱** 可访问项目地址 `https://gitcode.com/open-source-toolkit/e2db5` 获取 ACM-ICPC 历年竞真题及详解[^1]。此资源库提供了丰富的题目和解析资料,适合用于学习和备。 2. **优快云 博客及相关作者分享** 优快云 平台上多位博主(如渡梦酒)发布了关于 ACM 和 CCPC 的真题及其官方解答[^3]。虽然这些内容可能主要集中在特定区域或年度事,但仍可作为参考材料扩展视野。 3. **具体新疆赛区题目实例** 针对 2023 年国际大学生程序设计竞 (ACM-ICPC) 新疆赛区的比情况,在某些公开讨论区或者个人博客中有提及如何通过编程解决实际问题的方法论[^4]。例如下面展示了一道基于等差数列计算字符位置的经典例程: ```cpp #include<bits/stdc++.h> using namespace std; #define int long long signed main(){ int n, m, l; cin>>n>>m>>l; // 计算总和 S(n) int sum = (n)*(n+1)/2; // 找到剩余部分 R(k) int k = n - (m-1); int r = (k)*(k+1)/2; // 结果处理并输出字母形式 r = (sum - r + l ) % 26 ; if(r == 0){ cout<<"Z"; return 0; } char c = 'A' + r -1; cout<<c<<endl; return 0; } ``` 上述代码片段展示了利用数学公式快速解决问题的能力,这正是参加此类比所需要掌握的核心技能之一。 --- ### 注意事项 当从网络上查找历年的试题时,请注意尊重原作者劳动成果以及遵守相应版权规定。如果引用他人作品务必标明出处链接与声明信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值