zoukankan      html  css  js  c++  java
  • bzoj2909: Bipartite Numbers

    Description

    Bipartite Number是这样的一个正整数,他只能由两段相同的数组成,如44444411,10000000, 5555556,41,而4444114,44444则不是。
    现给你一个N,让你找到最小的Bipartite NumberX,使得X=NK(K是正整数,K>1),由于答案X可能很大,你需将其缩写转换为4个数字输出,即(高位数字长度,高位数字,低位数字长度,低位数字),如44444411为6 4 2 1,88888888888800000为12 8 5 0,N<=1e5,T<=20

    从小到大枚举位数,再枚举最高位,用一个表动态记录%N=a的形如(10^c-1)/9*b(c<当前位数,1<=|b|<=9)的数中最小和次小的一个,以便枚举最低位的值查询是否可行

    #include<cstdio>
    #include<cstring>
    int n,a1,a2,u1,u2,uu1,uu2;
    int f[100077][22][2],ed[100077],tk=0;
    inline int fix(int x){return x+(x>>31&n);}
    void ins(int p1,int p2,int v){
        if(ed[p1]!=tk){
            ed[p1]=tk;
            memset(f[p1],-1,sizeof(f[p1]));
        }
        f[p1][p2][0]=f[p1][p2][1];
        f[p1][p2][1]=v;
    }
    int cal(int v1,int v2){
        v2-=10;
        return (v2>0?v1:-v1)*10+v2;
    }
    void chk(int c1,int c2){
        if(~c1&&(a1==-1||cal(c1,c2)<cal(a1,a2)))a1=c1,a2=c2;
    }
    void find(int a,int b){
        if(ed[a]==tk)chk(f[a][b][1],b);
    }
    void findx(int a,int b,int c){
        if(ed[a]==tk){
            if(c==uu2){
                if(f[a][b][1]!=u2)chk(f[a][b][1],b);
                if(f[a][b][0]!=u2)chk(f[a][b][0],b);
            }else chk(f[a][b][1],b);
        }
    }
    void chk(){
        u1=-1;
        int ss[10],sp=0,p1,p2;
        for(int x=n;x;ss[++sp]=x%10,x/=10);
        for(p1=sp;p1>0&&ss[p1]==ss[sp];--p1);
        for(p2=p1-1;p2>0&&ss[p2]==ss[p1-1];--p2);
        if(p1&&!p2)u1=sp,u2=p1,uu1=ss[sp],uu2=ss[p1];
    }
    void cal(){
        if(n==1){
            puts("1 1 1 0");
            return;
        }
        ++tk;
        chk();
        a1=-1;
        for(int i=1,v=1;;++i,v=(v*10+1)%n){
            for(int a=1,z=v;a<=9;++a,z=fix(z+v-n)){
                if(i==u1&&a==uu1){
                    for(int b=0;b<=9;++b)if(b!=a)findx(z,10+b-a,b);
                }else for(int b=0;b<=9;++b)if(b!=a)find(z,10+b-a);
                if(a1!=-1){
                    printf("%d %d %d %d
    ",i-a1,a,a1,a+a2-10);
                    return;
                }
            }
            for(int a=1,z=v;a<=9;++a,z=fix(z+v-n)){
                ins(fix(-z),10+a,i);
                ins(z,10-a,i);
            }
        }
    }
    int main(){
        while(scanf("%d",&n)==1&&n)cal();
        return 0;
    }
  • 相关阅读:
    场景调研
    手机搜狗输入法体验
    1到一个整数之间1的个数
    寻找水王
    成套卖书最大优惠问题
    面向对象--多态
    抽象类和接口
    面向对象思想--继承
    面向对象思想--封装
    变量和参数传递
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7526682.html
Copyright © 2011-2022 走看看