整数分解与筛法 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 |
算法分析
其实挺简单的,只是输入有点阴,并输入处理好了,接下来按题意模拟即可,思路如下:
- 输入用字符串读入整行,两两一组,找出每组的P和E。
- 用快速幂计算,把积存起来。
- 对每组数据的值-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;
}

浙公网安备 33010602011771号