整数分解与筛法 Prime Land

在素数王国,大家都用一种素数进制数系统。这个系统里,每个正整数 x 都可以这样表示:设 {pi}i=0,1,2,... 是所有素数按从小到大的顺序排列。我们知道,x > 1 可以且仅可以用素数的幂的乘积唯一表示。也就是说,存在一个整数 k 和一组唯一确定的整数 \(e_k\), \(e_k-_1\), ... ,\(e_1\), \(e_0\),其中 \(e_k\) > 0,使得 这个序列

(\(e_k\), \(e_k-_1\), ... ,\(e_1\), \(e_0\))

就被称为 x 在素数进制数系统中的表示。

说实话,在素数进制里做加减法对我们来说有点怪怪的,甚至挺难的。素数王国的孩子们都得花好几年学会加减法。不过乘法和除法倒是很简单。

最近,有人从计算机王国度假回来,那儿用一种叫“计算机”的小聪明玩意儿。结果发现,计算机能让素数进制的加减法变得轻松多了。于是决定做个实验,让计算机帮忙做“减一”操作。

帮帮素数王国的人们,写个程序实现这个功能吧。

为了方便,我们这里用素数进制的表示法,只写出那些对应指数 \(e_i\)>0 的素数 \(p_i\) 和指数 \(e_i\),且按素数从大到小排列。

输入格式

输入由若干行组成(至少一行),每行(除了最后一行)包含一个大于 2 且不超过 32767 的正整数的素数进制表示。行内数字之间用一个空格分隔。最后一行是数字 0,表示输入结束。

输出格式

对于输入中除最后一行外的每一行,输出对应的整数减一后的素数进制表示。数字之间用一个空格分隔。输入最后的“0”行不对应任何输出。

样例

Input复制 Output复制
17 1 2 4
5 1 2 1 3 2
509 1 59 1 13 1 11 1 7 1 5 1 3 1 2 1
0

算法分析

其实挺简单的,只是输入有点阴,并输入处理好了,接下来按题意模拟即可,思路如下:

  1. 输入用字符串读入整行,两两一组,找出每组的P和E。
  2. 用快速幂计算,把积存起来。
  3. 对每组数据的值-1分解质因数,然后倒序输出。

坑点

  • 输入要加判断,以防TLE和RE(栽了7次qwq)。
  • 输出要倒叙输出,先输出质因数,再输出指数。
  • 要用快速幂,不然会超时。
  • 有多组数据,数组要清空。
#include<bits/stdc++.h>
using namespace std;
map<long long,int> cnt;
vector<long long> v;
long long sum = 1;
long long ksm(long long a,long long b){//快速幂模板
	long long t = 1;
	while(b){
        if(b%2==1){
            t = t*a;
        }
        a = a*a;
        b/=2;
    }
    return t;
}
void fj(long long x){//分解质因数
    for(long long i = 2; i<=x; i++){
    	if(x%i==0){
    		v.push_back(i);
		}
        while(x%i==0){
            cnt[i]++;
			x/=i;
        }
    }
}
int main(){
	ios::sync_with_stdio(0);//加速器
	cin.tie(0);
	cout.tie(0);
	while(1){//很阴的输入
		sum = 1;
		string s;
    	getline(cin,s);
    	if(s=="0"){
    		return 0;
    	}
    	s+=" ";
    	int i = 0;
    	int len = s.size();
    	while(i<len){
			int a = 0;
			int b = 0;
			while((i<len)/*注意要加判断,下面也一样!!!*/ && (s[i]>='0' && s[i]<='9')){
				a*=10;
				a+=s[i]-'0';
				i++;
			}
			while((i<len) && (s[i]<'0' || s[i]>'9')){
				i++;
			}
			while((i<len) && (s[i]>='0' && s[i]<='9')){
				b*=10;
				b+=s[i]-'0';
				i++;
			}
			while((i<len) && (s[i]<'0' || s[i]>'9')){
				i++;
			}
			sum*=ksm(a,b);
		}
		fj(sum-1);
		for(int i = v.size()-1; i>=0; i--){//输出
			cout<<v[i]<<" "<<cnt[v[i]]<<" ";
		}
		cout<<'\n';
		v.clear();//数组清空
		cnt.clear();
	}
	return 0;
}
posted @ 2026-06-14 14:20  xmgene  阅读(10)  评论(0)    收藏  举报