闲话 (无兴趣可空降)
- 这题折磨了我好久,为了调试,打了800多个字符(要知道我的正解才700多个字符),很短的代码,是我的心血。在漫漫OI路上,我总是被一些小错误,卡住一周甚至更多
也许是实力问题?,但也在其中收获很多。最后,也要感谢我的老师,为我引路。好潦草的一段话
ps.调试前后代码对比
调试中:
#include<bits/stdc++.h>
using namespace std;
int n,m,a,b,s,ans[10001],sum[10001],d=0;
inline int gcd(int x,int y){
if(!y) return x;
return gcd(y,x%y);
}
inline void jqsh(int t,int k,int l,int x,int y){
if(x<0||y<0) return;
m=gcd(x,y);
x=x/m;y=y/m;
if(x==1&&t==k-1){
cout<<x<<" "<<y<<endl;
sum[++sum[0]]=y;
for(int i=1;i<=sum[0];i++) cout<<sum[i]<<" ";
cout<<endl<<sum[0]<<" "<<ans[0]<<endl;
cout<<sum[sum[0]]<<" "<<ans[ans[0]]<<endl;
if((sum[sum[0]]<ans[ans[0]]&&sum[0]==ans[0])||!ans[0]||ans[0]>sum[0]){
ans[0]=sum[0];
for(int i=1;i<=ans[0];i++) ans[i]=sum[i];
if(d==1) cout<<"win"<<endl;
}
system("pause");
sum[0]--;
return;
}
else if(t==k-1) return;
for(int i=max(l+1,y/x-1);i<=(k-t)*y/x;i++){
sum[++sum[0]]=i;
if(d==1){
cout<<"!!!"<<endl;
cout<<t<<endl;
cout<<i<<endl;
cout<<x<<" "<<y<<endl;
cout<<"!!!"<<endl;
system("pause");
jqsh(t+1,k,i,x*i-y,y*i);
}
if((i==5&&t==0&&k==3)){
cout<<"****************"<<endl;
cout<<t<<endl;
cout<<i<<endl;
cout<<x<<" "<<y<<endl;
d=1;
jqsh(t+1,k,i,x*i-y,y*i);
cout<<"*****************"<<endl;
system("pause");
}
jqsh(t+1,k,i,x*i-y,y*i);
sum[0]--;
}
return;
}
int main(){
scanf("%d %d",&a,&b);
m=gcd(a,b);
a=a/m;b=b/m;
// for(int i=1;i<=a;i++)
if(a==1){
printf("%d\n",b);
return 0;
}
for(int i=2;;i++){
cout<<"*******"<<endl;
cout<<i<<endl;
system("pause");
sum[0]=0;
jqsh(0,i,1,a,b);
cout<<"*******"<<endl;
if(ans[0]) break;
}
for(int i=1;i<=ans[0];i++)
printf("%d ",ans[i]);
printf("\n");
return 0;
}
正解
#include<bits/stdc++.h>
using namespace std;
long long n,m,a,b,s,ans[10001],sum[10001];
inline long long gcd(long long x,long long y){
if(!y) return x;
return gcd(y,x%y);
}
inline void jqsh(int t,int k,long long l,long long x,long long y){
if(x<0||y<0) return;
m=gcd(x,y);
x=x/m;y=y/m;
if(x==1&&t==k-1&&y!=l){ //y!=l避免分数相等
sum[++sum[0]]=y;
if((sum[sum[0]]<ans[ans[0]]&&sum[0]==ans[0])||!ans[0]||ans[0]>sum[0]){
ans[0]=sum[0];
for(int i=1;i<=ans[0];i++) ans[i]=sum[i];
}
sum[0]--; //调了那么多,原来是少了这一句 QWQ
return;
}
else if(t==k-1) return;
for(int i=max(l+1,y/x-1);i<=(k-t)*y/x+1;i++){
sum[++sum[0]]=i;
jqsh(t+1,k,i,x*i-y,y*i); //分数通分
sum[0]--;
}
return;
}
int main(){
scanf("%lld %lld",&a,&b);
m=gcd(a,b);
a=a/m;b=b/m;
if(a==1){
printf("%lld\n",b);
return 0;
}
for(int i=2;;i++){
sum[0]=0;
jqsh(0,i,1,a,b);
if(ans[0]) break;
}
for(int i=1;i<=ans[0];i++)
printf("%lld ",ans[i]);
printf("\n");
return 0;
}
——————————————————————————————正文分割线————————————————————————
题干解析
- 好恶心的题干,分数枚举从小到大,不能相等,最小的最大…
思路
- 用迭代搜索,不断更新,分数要约分
剪枝
- 剪枝1:分数约分时用gcd。
- 剪枝2:循环上下限 (详见这位大神博客)
- 剪枝3:在搜索到只剩一个时,若x不为1,返回 (啊,好难描述详见代码吧)
- 剪枝4:如果当前分子分母小于0,返回
ps.最重要的,如果不想见祖宗,请开long long
- 代码在上面
本文分享了一道关于分数枚举的问题解决过程,通过迭代搜索并应用多种剪枝技巧找到最优解。从调试经历到最终代码实现,展示了作者在算法竞赛中的成长与心得。

6880

被折叠的 条评论
为什么被折叠?



