搜索——codevs1185 幸运数字

http://codevs.cn/problem/1185/
我们的模拟考,我靠;
钻石题,无题解;
我自然是没什么能耐,zzh大佬自然是秒了;
首先,我们达标找规律,发现一个结论;
n<=2000时答案个数不超过9个
在20以后就一定有解;
这个结论太好了;
然而其实也是对的;
至于证明,这个联系到关于博弈论的知识,我不是很会;
虽然我们知道最多只有9个数;
但是直接搜索9个数也是很难的;
因为一个数的范围太大了,我们要缩小;
那我们按位搜索
比如
一个数分解成
4+44+74+474
百位就是4
十位就是4+7+7
个位就是4+4+4+4
我们先1~9枚举会分解成几个数
我们再从n的最高位位开始枚举当前的位的数是什么(可以是0)
每位数最多9*7=63,我们可以方便理解为100;
如果枚举到0位,并且刚好n被分解,更新答案;

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define Ll long long
using namespace std;
int e[20][120],q[100],x[12],y[12],d[12],w[12],v[12][12];
int n,ii,o;
void calc(){
    memset(v,0,sizeof v);
    for(int i=o;i;i--)
        for(int k=0;k<=w[i];k++)
            if(4*k+7*(w[i]-k)==d[i]){
                for(int j=1;j<=w[i]-k;j++)v[i][j]=7;
                for(int j=1;j<=k;j++)v[i][j+w[i]-k]=4;
                break;
            }
    for(int i=ii;i;i--){
        int k=0;
        for(int j=o;j;j--)k=k*10+v[j][i];
        y[ii-i+1]=k;
    }
    for(int i=1;i<=ii;i++)
        if(y[i]<x[i]){
            for(int i=1;i<=ii;i++)x[i]=y[i];
            return;
        }else if(y[i]>x[i])return;
}
bool dfs(int x,int y,int z,int now){//当前枚举到第x位,总共分成y个数,这一位值因为z,now自己看 
    if(!x)if(!z)return calc(),1;else return 0;
    bool ans=0;
    for(int i=now;i<=y;i++)
        for(int j=1;j<=e[i][0];j++)
            if((z>=e[i][j])&&(((z-e[i][j])*10+q[x-1])/7<=y)){
                d[x]=e[i][j];w[x]=i;
                ans=ans|dfs(x-1,y,((z-e[i][j])*10+q[x-1]),i);
            }
    return ans;
}
bool check(int x,int y){
    for(int k=0;k<=y;k++)
        if(4*k+7*(y-k)==x)return 1;
    return 0;
}
int main()
{
    freopen("lucky.in","r",stdin);
    freopen("lucky.out","w",stdout);
    e[0][0]=1;
    for(int i=1;i<=100;i++)
        for(int j=1;j<=12;j++)
            if(check(i,j))
                e[j][++e[j][0]]=i;//e表示用i个47可以组成的数 
    scanf("%d",&n);
    if((n==1)||(n==2)||(n==3)||(n==5)||(n==6)||(n==9)||(n==10)||(n==13)||(n==17)){printf("No solution");return 0;}  
    for(;n;n/=10)q[++o]=n%10;
    for(ii=1;ii<=12;ii++){//ii是全局变量 
        x[1]=1e9;
        if(dfs(o,ii,q[o],0))break;
    }
    for(int i=1;i<=ii;i++)printf("%d ",x[i]);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值