1. 程式人生 > >BZOJ 3629 JLOI2014 聰明的燕姿 約數和+DFS

BZOJ 3629 JLOI2014 聰明的燕姿 約數和+DFS

ini pri spa etc ont read size void logs

根據約數和公式來拆s,最後再把答案乘出來,我們發先這樣的話遞歸層數不會太大每層枚舉次數也不會太多,然而我們再來個剪枝就好了

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
inline int read()
{
    int sum=0;
    char ch=getchar();
    while(ch<0||ch>9)ch=getchar();
    
while(ch>=0&&ch<=9) { sum=(sum<<1)+(sum<<3)+ch-0; ch=getchar(); } return sum; } vector<int> ans; int is[50000],Max=50000,prime[50000],sz; inline void Init() { for(int i=2;i<Max;i++) { if(!is[i]) prime[++sz]=i; for(int
j=1;prime[j]*i<Max;j++) { is[prime[j]*i]=1; if(i%prime[j]==0)break; } } } inline bool jud(int x) { if(x==1)return 0; int lim=(int)sqrt(x+0.5); for(int i=1;prime[i]<=lim;i++) if(x%prime[i]==0) return 0; return 1; } void dfs(int x,int s,int
Ans) { if(s==1) { ans.push_back(Ans); return; } int lim=(int)sqrt(s+0.5); if(prime[x]>lim) { if(jud(s-1)&&s-1>=prime[x]) { Ans*=s-1; ans.push_back(Ans); } return; } long long sum=0,get=1; for(int i=0;sum<=s;i++) { sum+=get; if(s%sum==0) dfs(x+1,s/sum,Ans*get); get*=prime[x]; } } int main() { //freopen("swallow.in","r",stdin); //freopen("swallow.out","w",stdout); int s; Init(); while(scanf("%d",&s)==1) { ans.clear(); dfs(1,s,1); printf("%d\n",ans.size()); if(ans.size()==0)continue; sort(ans.begin(),ans.end()); for(int i=0;i<ans.size();i++) printf("%d ",ans[i]); printf("\n"); } return 0; }

BZOJ 3629 JLOI2014 聰明的燕姿 約數和+DFS