质因数的性质(美登杯”上海市高校大学生程序设计邀请赛 (华东理工大学) E题)

本文探讨了在程序设计中如何高效地分解质因数,通过只筛选到数的平方根来优化算法。在‘美登杯’上海市高校大学生程序设计邀请赛 (华东理工大学) 的E题中,这一性质被巧妙地利用,使得在1e8的复杂度内可以完成对1e5个不超过1e6的数字的质因数分解。对于超过平方根的部分,若数值不为1,则直接认定为质因数。
摘要由CSDN通过智能技术生成

分解一个在 N范围内 的数      的  质因数

我们首先想到的是把 N 范围内 的所有素数O(N)的筛选出来,然后while跑质数表,来达到加速查找的目的。

但是现在 我们可以发现 , 一个数X , 它的质因数 肯定在 sqrt(X)内是 最多的

令 Y = sqrt(X) , 假设 Y现在是一个质数 , 那么 后面明显就不会有 X的质因数 , 所以 我们进行分解质因数的时候,可以只筛到sqrt(X)就可以了 , 假设我们现在要对 Q 个(1 <= Q <= 1e5) 数字进行筛选 , 每个数字 Ai 的大小是 (1 <= Ai <= 1e6)

那么可以在1e8 的复杂度内完成 。

bool valid[Maxn];
int prime[Maxn] , ast;
vector <int> G[Maxn>>2];
void getPrime(int n , int &ast){
	memset(valid , true , sizeof(valid));
	for(int i = 2 ; i <= n ; i++){
		if(valid[i]){
			ast++;
			prime[ast]=i;
		}
		for(int j = 1 ; (j<=ast) && (i*prime[j] <= n) ; j++){
			valid[i*prime[j]] = false;
			if(i % prime[j] == 0)	break;
		}
	}
}



int main()
{
	ast = 0;
	getPrime(1007 , ast);
	scanf(" %d %d",&N,&M);
	for(int i = 1 ; i <= N ; i++){
		int x;	scanf(" %d",&x);
		for(int j = 1 ; j <= ast ; j++){
			while(x % prime[j] == 0){
				G[i].push_back(prime[j]);
				x /= prime[j];
			}
		}
		if(x != 1)	G[i].push_back(x);
	}
}

超过了 sqrt(X) 部分的质因数 , 我们可以通过 X != 1 来判断 , 说明现在剩下的X必定是一个质因数 , 直接塞进vector即可

 

“美登杯”上海市高校大学生程序设计邀请赛 (华东理工大学)

这场比赛的 E题 就利用了这个性质,完美维护质因数。

代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <iostream>
#include <cmath>
#include <map>
#include <queue>
#include <algorithm>
#include <set>
#include <vector>
#include <stack>
#define Clear( x , y ) memset( x , y , sizeof(x) );
#define Qcin() std::ios::sync_with_stdio(false);
using namespace std;
typedef long long LL;
const int Maxn = 1e6 + 7;
const int Inf = 1e9 + 7;
const LL Mod = 1e9 + 7;
int N , M;

bool valid[Maxn];
int prime[Maxn] , ast;
vector <int> G[Maxn>>2];
void getPrime(int n , int &ast){
	memset(valid , true , sizeof(valid));
	for(int i = 2 ; i <= n ; i++){
		if(valid[i]){
			ast++;
			prime[ast]=i;
		}
		for(int j = 1 ; (j<=ast) && (i*prime[j] <= n) ; j++){
			valid[i*prime[j]] = false;
			if(i % prime[j] == 0)	break;
		}
	}
}

int Add , Sub;
struct edge{
	int l , r;
	int add , sub;
}tree[Maxn];

void Build(int l , int r , int x){
	tree[x].l = l , tree[x].r = r;
	tree[x].add = tree[x].sub = 0;
	if( l == r )	return;
	int mid = ( l + r ) / 2;
	Build( l , mid , x * 2 );
	Build( mid + 1 , r , x * 2 + 1 );
}

void PushDown( int x ){
	if(tree[x].add || tree[x].sub){
		if(tree[x<<1].add >= tree[x].sub)	tree[x<<1].add -= tree[x].sub;
		else	tree[x<<1].sub += (tree[x].sub - tree[x<<1].add) , tree[x<<1].add = 0;
		if(tree[x<<1|1].add >= tree[x].sub)	tree[x<<1|1].add -= tree[x].sub;
		else	tree[x<<1|1].sub += (tree[x].sub - tree[x<<1|1].add) , tree[x<<1|1].add = 0;
		tree[x<<1].add += tree[x].add;
		tree[x<<1|1].add += tree[x].add;
		tree[x].sub = tree[x].add = 0;
	}
}

void Update_line( int L , int R , int add , int x ){
	if( L <= tree[x].l && tree[x].r <= R ){
		if(add == 1){
			tree[x].add++;
		} else {
			if(tree[x].add)	tree[x].add--;
			else	tree[x].sub++;
		}
		return;
	}
	PushDown(x);
	int mid = ( tree[x].l + tree[x].r ) / 2;
	if( L <= mid )	Update_line( L , R , add , x * 2 );
	if( R > mid )	Update_line( L , R , add , x * 2 + 1 );
}

void Query(int L , int R , int x){
	if(L <= tree[x].l && tree[x].l == tree[x].r){
		Add = tree[x].add , Sub = tree[x].sub;
		return;
	}
	PushDown(x);
	int mid = ( tree[x].l + tree[x].r ) / 2;
	if(L <= mid)	Query(L , R , x * 2);
	if(R > mid)	Query(L , R , x * 2 + 1);
	return;
}

LL Qpow(LL x , LL y){
	LL res = 1;
	while(y){
		if(y & 1)	res = res * x % Mod;
		x = x * x % Mod;
		y = y >> 1;
	}
	return res % Mod;
}

int main()
{
	ast = 0;
	getPrime(1007 , ast);
	scanf(" %d %d",&N,&M);
	for(int i = 1 ; i <= N ; i++){
		int x;	scanf(" %d",&x);
		for(int j = 1 ; j <= ast ; j++){
			while(x % prime[j] == 0){
				G[i].push_back(prime[j]);
				x /= prime[j];
			}
		}
		if(x != 1)	G[i].push_back(x);
	}
	Build(1 , N , 1);
	while(M--){
		int op;	scanf(" %d",&op);
		int L , R;
		if(op == 1){
			scanf(" %d %d",&L,&R);
			Update_line(L , R , 1 , 1);
		} else if(op == 2){
			scanf(" %d %d",&L,&R);
			Update_line(L , R , -1 , 1);
		} else {
			int u;
			scanf(" %d",&u);
			Query(u , u , 1);
			if(Sub >= G[u].size())	printf("1\n");
			else {
				LL ans = 1;
				for(int i = Sub ; i < G[u].size() ; i++){
					ans *= (LL)G[u][i];
				}
				ans = (LL)ans * Qpow((LL)G[u][Sub] , (LL)Add) % Mod;
				printf("%lld\n",ans % Mod);
			}
		}
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
城市应急指挥系统是智慧城市建设的重要组成部分,旨在提高城市对突发事件的预防和处置能力。系统背景源于自然灾害和事故灾难频发,如汶川地震和日本大地震等,这些事件造成了巨大的人员伤亡和财产损失。随着城市化进程的加快,应急信息化建设面临信息资源分散、管理标准不统一等问,需要通过统筹管理和技术创新来解决。 系统的设计思路是通过先进的技术手段,如物联网、射频识别、卫星定位等,构建一个具有强大信息感知和通信能力的网络和平台。这将促进不同部门和层次之间的信息共享、交流和整合,提高城市资源的利用效率,满足城市对各种信息的获取和使用需求。在“十二五”期间,应急信息化工作将依托这些技术,实现动态监控、风险管理、预警以及统一指挥调度。 应急指挥系统的建设目标是实现快速有效的应对各种突发事件,保障人民生命财产安全,减少社会危害和经济损失。系统将包括预测预警、模拟演练、辅助决策、态势分析等功能,以及应急值守、预案管理、GIS应用等基本应用。此外,还包括支撑平台的建设,如接警中心、视频会议、统一通信等基础设施。 系统的实施将涉及到应急网络建设、应急指挥、视频监控、卫星通信等多个方面。通过高度集成的系统,建立统一的信息接收和处理平台,实现多渠道接入和融合指挥调度。此外,还包括应急指挥中心基础平台建设、固定和移动应急指挥通信系统建设,以及应急队伍建设,确保能够迅速响应并有效处置各类突发事件。 项目的意义在于,它不仅是提升灾害监测预报水平和预警能力的重要科技支撑,也是实现预防和减轻重大灾害和事故损失的关键。通过实施城市应急指挥系统,可以加强社会管理和公共服务,构建和谐社会,为打造平安城市提供坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值