hdu1664 Different Digits

对于任意 n ,其倍数中,一定有由两个不同数字组成的数。因为将只由a0<a<10组成的十进制数升序排序,对于模 n 一定会产生一个循环节,而将任意两个模n同余的数相减,就可以得到只由 a 0组成的 n 的倍数。
这题让我想起了前几天同学给我看的一道水题(Poj2551),这题提到对于任意奇数n 5/|n ,其倍数都一定有是由连续的1组成的十进制数,其实,只要满足条件的 n ,其倍数都一定有是由连续的a0<a<10组成的十进制数。做这题时,我顺带证明了一下。
将由 a 组成的连续的十进制数升序排序,显然有:

ai=10ai1+a

同样,该序列一定在模 n 下构成一个循环节,且一定存在i,使

aia(modn)


10ai1+a10ai1ai1ai1a(modn)0(modn)0(modngcd(10,n))0(modn)

当然,在这题中,先检查 n <script type="math/tex" id="MathJax-Element-18">n</script>是否有只由1个数字组成的倍数,再bfs求出由2个数字组成的最小的倍数就可以了。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define clr(a) memset(a,0,sizeof(a))
typedef long long ll;
struct nd{
    char x;
    int mx,sx;
    int fa;
}qe[200010];
int _hd,_tl;
int bd[70010],_bd=0;
int _ck(int x,int a){
    int _a=a%x,r=1;
    ++_bd;
    while(1){
        if(bd[_a]==_bd)return 0;
        if(!_a)return r;
        bd[_a]=_bd,++r;
        _a=(_a*10+a)%x;
    }
};
int szle;
char sz[70010];
void _psh(int x){
    if(qe[x].fa)_psh(qe[x].fa);
    sz[qe[x].mx]=qe[x].x;
};
char tz[70010];
void __psh(int x){    
    if(qe[x].fa)__psh(qe[x].fa);
    tz[qe[x].mx]=qe[x].x;
};
bool _mp(){
    int i;
    for(i=1;sz[i]==tz[i];++i);
    return tz[i]<sz[i];
};
void __ck(int x,int a,int b){
    _hd=0,_tl=1;
    qe[0].mx=0;qe[0].sx=x;
    ++_bd;
    bool fg=0;int i,t;
    for(;_hd<_tl;++_hd){
        if(bd[qe[_hd].sx]==_bd)continue;
        if(!qe[_hd].sx)break;
        bd[qe[_hd].sx]=_bd;
        t=(qe[_hd].sx*10+a)%x;
        if(bd[t]!=_bd){
            qe[_tl].fa=_hd;
            qe[_tl].sx=t;
            qe[_tl].x=char(a+'0');
            qe[_tl].mx=qe[_hd].mx+1;
            ++_tl;
            if(!_hd&&!a)--_tl;
        }
        t=(qe[_hd].sx*10+b)%x;
        if(bd[t]!=_bd){
            qe[_tl].fa=_hd;
            qe[_tl].sx=t;
            qe[_tl].x=char(b+'0');
            qe[_tl].mx=qe[_hd].mx+1;
            ++_tl;
            if(!_hd&&!b)--_tl;
        }
    }
    if(_hd!=_tl){
        if(!szle)szle=qe[_hd].mx,_psh(_hd);
        else{
            if(szle>qe[_hd].mx)szle=qe[_hd].mx,_psh(_hd);
            else{
                if(szle==qe[_hd].mx){
                    __psh(_hd);
                    if(_mp()){
                        for(i=1;i<=szle;++i)
                            sz[i]=tz[i];
                    }
                }
            }
        }
    }
};
int n;
bool cl(){
    scanf("%d",&n);
    if(!n)return 0;
    int i,t,le=0;char ri;bool fg=0;
    for(i=1;i<10;++i){
        t=_ck(n,i);
        if(!le)
            le=t,ri=char(i+'0');
        else if(t&&le>t)
            le=t,ri=char(i+'0');
    }
    if(le){
        for(i=0;i<le;putchar(ri),++i);
        putchar('\n');
    }
    else{
        szle=0;
        for(i=0;i<10;++i)for(t=i+1;t<10;++t)
            __ck(n,i,t);
        for(i=1;i<=szle;putchar(sz[i++]));
        putchar('\n');
    }
    return 1;
};
int main(){
#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif
    while(cl());
    return 0;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值