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\n",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; }