【BZOJ3629】[JLOI2014]聪明的燕姿 数学+搜索

本文详细解析了一道关于求解特定约数和的数学题目,介绍了算数基本定理及约数和定理,并通过搜索算法实现解决方案。

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

我遇见谁会有怎样的对白
我等的人他在多远的未来
我听见风来自地铁和人海
我排着队拿着爱的号码牌
——孙燕姿《遇见》
题意:给出一个数S,求约数和等于S的数。
作为一道数学题,首先需要了解一些数学定理:
算数基本定理:
任何一个大于1的自然数N,都可以唯一分解成有限个质数的乘积N=P^a₁ P^a…Pn^an,这里P₁<P₂<…<Pn均为质数,其诸指数ai正整数。
这样的分解称为N的标准分解式。
约数和定理:
对于任意一个大于1的正整数N可以分解正整数:N=P^a₁ P^a…Pn^an则由约数个数定理可知N的正约数有(a+1)(a₂+1)(a₃+1)…(an+1)个,那么N(a₁+1)(a₂+1)(a₃+1)…(an+1)正约数的和为f(N)=(P^0+P^1+P^2+…P^a)(P^0+P^1+P^2+…P^a)…(Pn^0+Pn^1+Pn^2+…Pn^an)
至此,搜索算法很显然地露出水面——穷举Pi及其对应ai进行搜索。
①若当前数可表示成一个并未搜索过的质数与1的和,则之前搜索过的数与这个质数的乘积符合题意。
②对于每一个未被搜索过且平方小于当前数的质数,则枚举所有可能符合题意的ai进行递归搜索。
这样,此题便被完美解决。
【吐槽】当时JLOI时由于考场内由于台式机与投影仪的连接出现问题,评测机是一个临时借来的笔记本电脑——CPU慢得很恐怖,令我的卡时限的暴搜直接不解释地TLE……
顺便希望我所等待的那个人早日到来!!!
注:时至今日,我的代码仍然处于 BZOJ 榜首(100MS&108MS)且 Code_Length 1111 B!
后来发生了一个惨(xi)绝(da)人(pu)寰(ben)的事情,这份代码被同屋的大神在时间上超越了……于是******,终于重夺 Rank 1~~时间仅用80ms~~
[JLOI2014]聪明的燕姿 C++代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define N 100000
int p[N+5],cnt,s,ans,num[N+5];
bool flag[N+5];
void getprime()
{
	for(int i=2;i<=N;i++)
	{
		if(!flag[i]) p[++cnt]=i;
		for(int j=1; i*p[j]<=N; j++)
		{
			flag[i*p[j]]=1;
			if(i%p[j]==0) break;
		}
	}
}
bool isprime(int x)
{
	if(x==1) return false;
	if(x<=N) return !flag[x];
	for(int i=1;p[i]*p[i]<=x;i++)
		if(x%p[i]==0) return false;
	return true;
}
void dfs(int last,int now,int tot)
{
	if(tot==1){ num[++ans]=now; return; }
	if(tot-1>p[last]&&isprime(tot-1))
		num[++ans]=now*(tot-1);
	for(int i=last+1; p[i]*p[i]<=tot; i++)
		for(int tnum=p[i]+1,t=p[i]; tnum<=tot; t*=p[i],tnum+=t)
			if(tot%tnum==0)
				dfs(i,now*t,tot/tnum);
}
int main()
{
	getprime();
	while(scanf("%d",&s)!=EOF)
	{
		ans=0;
		dfs(0,1,s);
		cout<<ans<<endl;
		sort(num+1,num+ans+1);
		for(int i=1; i<=ans; i++)
			printf("%d%c",num[i],i==ans?'\n':' ');
	}
}


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值