1629:聪明的燕姿
1629:聪明的燕姿
时间限制: 1000 ms 内存限制: 524288 KB
提交数: 103 通过数: 53
【题目描述】
城市中人们总是拿着号码牌,不停寻找,不断匹配,可是谁也不知道自己等的那个人是谁。
可是燕姿不一样,燕姿知道自己等的人是谁,因为燕姿数学学得好!燕姿发现了一个神奇的算法:假设自己的号码牌上写着数字 S
,那么自己等的人手上的号码牌数字的所有正约数之和必定等于 S
。
所以燕姿总是拿着号码牌在地铁和人海找数字(喂!这样真的靠谱吗)可是她忙着唱《绿光》,想拜托你写一个程序能够快速地找到所有自己等的人。
【输入】
输入包含 k
组数据。
对于每组数据,输入包含一个号码牌S
。
【输出】
对于每组数据,输出有两行,第一行包含一个整数 m
,表示有 m
个等的人。
第二行包含相应的 m
个数,表示所有等的人的号码牌。
注意:你输出的号码牌必须按照升序排列。
【输入样例】
42
【输出样例】
3 20 26 41
【提示】
数据范围与提示
对于 100% 的数据,k≤100, S≤2×109
。
其实这道题一点都不难。
解答本题的关键在于对唯一分解定理和约数和公式的理解。分解数即可
代码中left表示被剩下的未被分解的数,sum'表示当前得到的结果,pos表示检索第几个质数。
#include<bits/stdc++.h> #define int long long using namespace std; const int N=1e6+1; bool mark[N]; int prime[N],tot,ans[N],S; inline void Pre() {int i,j,cnt=0;for(i=2;i<=N;i++){if(!mark[i]) {mark[i]=1;prime[++cnt]=i;}for(int j=1;j<=cnt&&prime[j]<=N/i;j++){mark[i*prime[j]]=1;if(i%prime[j]==0) break;}}//for(int i=1;i<=100;i++)//printf("%d ",prime[i]); } inline bool judge(int x) {for(int i=2;i<=sqrt(x);i++)if(x%i==0) return false;return true; } void dfs(int pos,int sum,int left) {if(left==1){ans[++tot]=sum;return ;}if(judge(left-1)&&left>prime[pos]) {ans[++tot]=sum*(left-1);}for(int i=pos;prime[i]*prime[i]<=left;i++){int Sum=prime[i]+1,tmp=prime[i];for(;Sum<=left;tmp*=prime[i],Sum+=tmp){if(left%Sum==0)dfs(i+1,sum*tmp,left/Sum);}} } signed main() {Pre();while(~scanf("%lld",&S)){tot=0;dfs(1,1,S);sort(ans+1,ans+tot+1);printf("%lld\n",tot);for(int i=1;i<=tot;i++)printf("%lld ",ans[i]);if(tot) puts("");}return 0; }
最后,值得注意的是这道题的输出有坑,得自己去WA下试试才知道
转载于:.html
1629:聪明的燕姿
1629:聪明的燕姿
时间限制: 1000 ms 内存限制: 524288 KB
提交数: 103 通过数: 53
【题目描述】
城市中人们总是拿着号码牌,不停寻找,不断匹配,可是谁也不知道自己等的那个人是谁。
可是燕姿不一样,燕姿知道自己等的人是谁,因为燕姿数学学得好!燕姿发现了一个神奇的算法:假设自己的号码牌上写着数字 S
,那么自己等的人手上的号码牌数字的所有正约数之和必定等于 S
。
所以燕姿总是拿着号码牌在地铁和人海找数字(喂!这样真的靠谱吗)可是她忙着唱《绿光》,想拜托你写一个程序能够快速地找到所有自己等的人。
【输入】
输入包含 k
组数据。
对于每组数据,输入包含一个号码牌S
。
【输出】
对于每组数据,输出有两行,第一行包含一个整数 m
,表示有 m
个等的人。
第二行包含相应的 m
个数,表示所有等的人的号码牌。
注意:你输出的号码牌必须按照升序排列。
【输入样例】
42
【输出样例】
3 20 26 41
【提示】
数据范围与提示
对于 100% 的数据,k≤100, S≤2×109
。
其实这道题一点都不难。
解答本题的关键在于对唯一分解定理和约数和公式的理解。分解数即可
代码中left表示被剩下的未被分解的数,sum'表示当前得到的结果,pos表示检索第几个质数。
#include<bits/stdc++.h> #define int long long using namespace std; const int N=1e6+1; bool mark[N]; int prime[N],tot,ans[N],S; inline void Pre() {int i,j,cnt=0;for(i=2;i<=N;i++){if(!mark[i]) {mark[i]=1;prime[++cnt]=i;}for(int j=1;j<=cnt&&prime[j]<=N/i;j++){mark[i*prime[j]]=1;if(i%prime[j]==0) break;}}//for(int i=1;i<=100;i++)//printf("%d ",prime[i]); } inline bool judge(int x) {for(int i=2;i<=sqrt(x);i++)if(x%i==0) return false;return true; } void dfs(int pos,int sum,int left) {if(left==1){ans[++tot]=sum;return ;}if(judge(left-1)&&left>prime[pos]) {ans[++tot]=sum*(left-1);}for(int i=pos;prime[i]*prime[i]<=left;i++){int Sum=prime[i]+1,tmp=prime[i];for(;Sum<=left;tmp*=prime[i],Sum+=tmp){if(left%Sum==0)dfs(i+1,sum*tmp,left/Sum);}} } signed main() {Pre();while(~scanf("%lld",&S)){tot=0;dfs(1,1,S);sort(ans+1,ans+tot+1);printf("%lld\n",tot);for(int i=1;i<=tot;i++)printf("%lld ",ans[i]);if(tot) puts("");}return 0; }
最后,值得注意的是这道题的输出有坑,得自己去WA下试试才知道
转载于:.html
发布评论