【题解】P4397 [JLOI2014]聪明的燕姿
\(Description:\)
给出s,找出所有约束和为s的数
\(Sample\) \(Input:\)
42
\(Sample\) \(Output:\)
3
20 26 41
数论普遍我都没思路。。。
一个白天就调了这么一道题,不如刷刷矩乘愉悦一下。。。
考虑两个定理:
唯一分解定理(没有鸟用,好像基本都知道
\(S=\prod_{i=1}^{n}p_i^{c_i}\)
因数和定理:
\(X=\prod_{i=1}^{n}(\sum_{j=0}^{c_i} p_i^{j})\)
这题其实就是想让从X推导到p,c。
考虑搜索,每次枚举每个质数和他的次数
传入三个参: 当前还要分解的数,分解到第几个质数,当前数是多少。
一般只要筛到\(\sqrt X\)就可以了
但要特别注意因数有一个大于根号x,那就要特判一下,如果剩下还要分解的数减1是质数且大于当前要用的质数,那也得加入答案。
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,cnt,num,opt;
const int MAXN=50000;
const int MAXM=100000;
int a[]={0,2,3,5,7,11};
int v[MAXM+5],p[MAXN+5];
int ans[MAXN+5];
inline int power(int a,int b,int p){
int ret=1;
for(;b;a=(a*a)%p,b>>=1) if(b&1) ret=(ret*a)%p;
return ret;
}
inline bool MR(int n){
if(n==1 || n==0) return 0;
if(n==2 || n==3) return 1;
for(int i=1;i<=5;++i) if(n==a[i]) return 1;
for(int i=1;i<=5;++i){
if(power(a[i],n-1,n)%n!=1) return 0;
}
return 1;
}
inline void dfs(int now,int k,int s){
if(now==1){
ans[++cnt]=s;
return;
}
if(MR(now-1) && now>p[k]) ans[++cnt]=s*(now-1);
for(int i=k;p[i]*p[i]<=now && i<=num;++i){
int sum=p[i]+1;
int t=p[i];
for(;sum<=now;t*=p[i],sum+=t)
if(now%sum==0)
dfs(now/sum,i+1,s*t);
}
}
signed main(){
v[1]=1;
for(int i=2;i<=MAXM;++i){
if(v[i]==0) p[++num]=i;
for(int j=1;j<=num && p[j]*i<=MAXM;++j){
v[i*p[j]]=1;
if(i%p[j]==0) break;
}
}
while(~scanf("%lld",&n)){
cnt=0;
dfs(n,1,1);
sort(ans+1,ans+cnt+1);
printf("%lld\n",cnt);
for(int i=1;i<=cnt;++i) printf("%lld ",ans[i]);
if(cnt) putchar('\n');
}
return 0;
}