题面:
主要是理解思想,建议:代码还是自己写
主要有三点:
1. 确定搜索层数
2. 适当剪枝(你会发现:emmm,常见的剪枝就可以满足啦)
3. 一些公式应该自己进行通分、推导
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define LL long long
#define MAXN 1000006
using namespace std;
inline int wread(){
char c=getchar ();int flag=1,wans=0;
while (c<'0'||c>'9'){if (c=='-') flag=-1;c=getchar ();}
while (c>='0'&&c<='9'){wans=wans*10+c-'0';c=getchar ();}
return wans*=flag;
}
int n,m;
int top=1;
int sav[MAXN],savt;
int pr[MAXN];
bool F;
LL gcd (LL a,LL b){
if (!b) return a;
return gcd(b,a%b);
}
//top 限制层数
//savt 保存的数组的编号
//F 判断是否成功
//St 最小的起点
void dfs (int ceng,int la,int U,int D){
//ceng:层数
//la:上一个所选择的分母 即1/la
//U:总和的分子
//D:总和的分母
if (ceng==top) {
int nU(n*D-U*m),nD(m*D);
if (nU<0 || nD <0) return ;
int gcdud(gcd(nU,nD));
if (nU/gcdud==1){
sav[ceng]=nD/gcdud;
if (sav[ceng]<=la) return ;
if (sav[ceng] >= pr[ceng]) return ;
F=true;
for (int i=1;i<=ceng;++i){
pr[i]=sav[i];
}
}
return ;
}
int shen_c((top+1-ceng));
double Lin;
if (ceng==1)
Lin=(m*shen_c*1.0)/(n*1.0);
else
Lin=(m*D*shen_c*1.0) / ( n*D*1.0 - U*m*1.0 );
int maxi=Lin;
for (int i=la+1;i<=maxi;++i){
if (ceng==1) {
sav[ceng]=i;
dfs (ceng+1,i,1,i);
}
else {
int nU=U*i+D,nD=D*i;
int sam(gcd(nU,nD));
sav[ceng]=i;
dfs(ceng+1,i,nU/sam,nD/sam);
}
}
return ;
}
void solve (){
memset (pr,0x3f3f3f3f,sizeof pr);
int St=m/n;
if (n*St!=m) St++;
while (true){
++top;
memset (sav,0,sizeof sav);
F=false;
dfs(1,St-1,0,0);
if (F) {
for (int i=1;i<=top;++i){
printf("%d ",pr[i]);
}
break;
}
}
return ;
}
int main (){
n=wread();m=wread();// n/m
if (n==1) {
printf("%d %d\n",n,m);
return 0;
}
solve();
return 0;
}