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