这是DFS经典题目,经常考
题目
Description
给出数字P,Q,A,N,代表将分数P/Q分解成至多N个分数之和,这些分数的分子全为1,且分母>的乘积不超过A。例如当输入数据为2 3 120 3时,我们可以得到以下几种分法: 3/2=1/3+1/3 =1/2+1/6 =1/4+1/4+1/6 =1/3+1/6+1/6
Input
本题含有多组测试数据,每组给出四个数P,Q,A,N,其中 p,q <= 800, A <= 12000,N ><= 7.当输入的四个数均为0时,代表测试结束.
Output
针对每组数据,输出共有多少种不同的分法。
Sample Input
2 3 120 3 2 3 300 3 2 3 299 3 2 3 12 3 2 3 12000 7 54 795 12000 7 2 3 300 1 2 1 200 5 2 4 54 2 0 0 0 0
Sample Output
4 7 6 2 42 1 0 9 3
解法
找到每个值的关系,判断范围,然后约分,如果符合就计数
代码
包含注释:(不含注释的在下面)
#include<bits/stdc++.h>//c++标准头文件
using namespace std;//c++命名空间
int tot,vis[10086],p,q,a,n;//变量
int cj(int p1,int q1,int p2,int q2) {//判断
return p1*q2-q1*p2;
}
void js(int &p1,int &q1,int p2,int q2) {//计算
p1=p1*q2-p2*q1;
q1*=q2;
}
void dfs(int zm,int zd,int pre,int dep,int sum){
int xm,xd;
if(sum==n+1&&zm!=0) return;
if(sum<=n+1&&zm==0){
tot++;//满足要求退出
return;
}
for(int d=pre;d<=dep;d++) {
if(cj(zm,zd,1,d) < 0) continue;//跳过
js(xm = zm,xd=zd,1,d);
if(cj(xm,xd,n - sum,d)>0) break;//退出
dfs(xm,xd,d,dep/d,sum+1);
}
}
int main() {
while(cin>>p>>q>>a>>n,p!=0){//保证无0
tot=0;
dfs(p,q,1,a,1);
cout<<tot<<endl;
}
}
无注释代码:
#include<bits/stdc++.h>
using namespace std;
int tot,vis[10086],p,q,a,n;
int cj(int p1,int q1,int p2,int q2) {
return p1*q2-q1*p2;
}
void js(int &p1,int &q1,int p2,int q2) {
p1=p1*q2-p2*q1;
q1*=q2;
}
void dfs(int zm,int zd,int pre,int dep,int sum){
int xm,xd;
if(sum==n+1&&zm!=0) return;
if(sum<=n+1&&zm==0){
tot++;
return;
}
for(int i=pre;i<=dep;i++) {
if(cj(zm,zd,1,i) < 0) continue;
js(xm = zm,xd=zd,1,i);
if(cj(xm,xd,n - sum,i)>0) break;
dfs(xm,xd,i,dep/i,sum+1);
}
}
int main() {
while(cin>>p>>q>>a>>n,p!=0){
tot=0;
dfs(p,q,1,a,1);
cout<<tot<<endl;
}
}
建议还是自己深入学一下,真正学习靠自己的理解
如果代码有问题可以在评论区找我