【题解】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;
}
posted @ 2019-04-03 19:41  章鱼那个哥  阅读(219)  评论(0编辑  收藏  举报