CCF CSP 202312-2因子化简

题目

试题编号 202312-2
试题名称 因子化简
时间限制 2s
内存限制 512MB
问题描述 CCF CSP 202312-2因子化简_第1张图片
输入输出 CCF CSP 202312-2因子化简_第2张图片
样例 CCF CSP 202312-2因子化简_第3张图片
样例解释 CCF CSP 202312-2因子化简_第4张图片

题目分析

我的思路很简单。
埃氏筛素数法筛一下 2 − 1 0 5 2-10^{5} 2105的素数。这里要知道这样一个素数原理,即:
任意的大于0整数,其质因子分解最多只有1个质因子大于 n \sqrt{n} n 且该因子一定是一次幂
比如: 42 = 2 ∗ 3 ∗ 7 42=2*3*7 42=237。7是大于 42 \sqrt{42} 42 的质因子,又比如 36 = 2 2 ∗ 3 2 36=2^2*3^2 36=2232没有大于6的质数因子。
很简单自己证明下就可以。n最大是 1 0 10 10^{10} 1010,因此只需要筛一下 2 − 1 0 5 2-10^{5} 2105以内的素数即可。在筛选后执行下面的步骤。 p r i m e i prime_i primei不大于 n \sqrt{n} n ,则判断
n % ( p r i m e i k ) = = 0 n \%(prime_i^k)==0 n%(primeik)==0
如果不为0,则说明要舍弃这个素数的项,从k开始往0找 p r i m e i prime_i primei的指数count_k(因为k不超过10,从10开始向下找不费时间)。找到后更新
n = n / p r i m e i c o u n t _ k n=n/prime_i^{count\_k} n=n/primeicount_k同时要记录一个nn,是将 p r i m e i prime_i primei完全除尽的结果。一直找到某个素数大于n或者等于n。这里注意下等于n的话要直接输出1,因为k不会为1。
在把 2 − 1 0 5 2-10^{5} 2105内的所有素数都找完后还没输出的话(sign=0),那么就判断下nn的值,如果nn不是1,说明nn等于那个大于 n \sqrt{n} n 的素数,就输出n/nn即可(因为大于 n \sqrt{n} n 的素数指数一定是1).如果nn为1,那就输出n。

AC代码(100分)

#include <stdio.h>
#include <string.h>
#include <vector>
#include <cmath>
#include <iostream>
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define rep(i,a,n) for(ll i=a;i<n;i++)
using namespace std;
ll quick(ll d,int z){
	ll ans=1;
	while(z){
		if(z&1)
			ans*=d;
		d*=d;
		z>>=1;
	}
	return ans;
}
int q,k;
ll n;
const int p=100000;
int prime[100001];
vector<int>qq;
void set_prime(int x){
	rep(i,2,x+1){
		int index=2;
		if(prime[i]==0){
			qq.push_back(i);
			while(index*i<=x){
				if(!prime[index*i]){
					prime[index*i]=1;
				}
				index++;
			}			
		}
	}
} 
int main(){
	mem(prime);
	set_prime(p);
	scanf("%d",&q);
	while(q--){
		scanf("%lld%d",&n,&k);
		if(n<=p&&prime[n]==0){
			printf("%lld\n",1);
		}
		else{
			ll nn=n;
			double sqn=sqrt(n);
			int sign=0;
			rep(i,0,qq.size()){
				int y=qq[i];
				if(y>sqn)break;
				if(n==y){
					printf("%lld\n",1);
					sign=1;
					break;
				}
				else if(n<y){
					printf("%lld\n",n);
					sign=1;
					break;
				}
				else if(n%y!=0)continue;
				else{
					int count_k=0;
					ll temp=n;
					while(temp%y==0){
						count_k++;
						temp/=y;
						nn/=y;
					}
					if(count_k<k){
						n=temp;
					}
				}
			}
			if(!sign){
				if(nn!=1)printf("%lld\n",n/nn);
				else printf("%lld\n",n);					
			}
		}
	}
	return 0;
}
/*
3
2155895064 3
2 2
10000000000 10
*/

你可能感兴趣的:(csp,算法,c语言)