哥为了来年交过好运,大年三十特地上来刷这题,结果就蛋疼到了11:50才写完,不过很高兴能够1A,希望今年事事顺利!
题目要求对一个给定的自然数,求出一个符合规定的的降序列,这个规则就是每次从数列前一项减去几个数位,而这几个数位构成的“合法自然数”必须又恰好是该项的约数。注意到单调减的特性,很容易想到记忆化,但是数据范围十亿以内,不能直接存表。注意到每一个合法的约数都是该数的“子序列”,因此可以把数位的使用状态使用二进制子集表示,于是可以把数组规模压缩到 1<<9。
剩余的就是比较繁琐的细节,特别要注意一个合法的Subfactor 必须是一个自然数,大于1小于该项本身,并且不能是多重0或前导0。
1#include<cstdio>
2#include<cstring>
3int dp[1<<10][2];
4int n;
5
6int makeNum(unsigned long cnt){
7 char str1[11],str2[11];
8 int len1,len2=0;
9 int inter;
10 len1=sprintf(str1,"%d",n);
11 for(int i=len1-1;i>-1;--i)
12 if(cnt&(1<<i))
13 str2[len2++]=str1[len1-1-i];
14 str2[len2]='\0'; sscanf(str2,"%d",&inter);
15 if(inter==0||str2[0]!='0') return inter;
16 else return -1; // 非法前导0
17}
18
19unsigned long clear(unsigned long cnt){
20 char str[11];
21 bool have;
22 unsigned long l=1;
23 int i,len=sprintf(str,"%d",n);
24 if( makeNum(cnt)!=0 ){ // 去前导0
25 for(have=i=0;i<len&&(have==false);i++){
26 if(str[i]!='0'&& ((cnt>>len-1-i)&l) ) have=true;
27 if(str[i]=='0'&& ((cnt>>len-1-i)&l) ) cnt=cnt&(~(l<<len-1-i));
28 }
29 }else{ // 排除 "0000 "
30 for(have=i=0;i<len;i++)
31 if(!have&& ((cnt>>len-1-i)&l) ) have=true;
32 else
33 if( have&& ((cnt>>len-1-i)&l) ) cnt=cnt&(~(l<<len-1-i));
34 }
35 return cnt;
36}
37
38int dfs(unsigned long s,int *next){
39 int len,cnt1,cnt2;
40 if(dp[s][0]==0){
41 cnt1=makeNum(s);
42 for(unsigned long i=0; ;i=(i-s) & s){
43 if(i==s) break;
44 if(i!=0){
45 if( (cnt2=makeNum(i))>1 && cnt1%cnt2==0 ){
46 len=dfs(clear(s&(~i)),next); // 和谐~
47 if( dp[s][0]<len ||
48 (dp[s][0]==len && makeNum(dp[s][1])>makeNum(*next)) ){
49
50 dp[s][0]=len;
51 dp[s][1]=*next;
52 }
53 }
54 }
55 }
56 ++dp[s][0];
57 }
58 *next=s;
59 return dp[s][0];
60}
61
62int main(){
63 char str[11];
64 int k,i,next;
65 unsigned long s;
66 while(scanf("%d",&n),n){
67 for(i=0;i<(1<<9);++i){ dp[i][0]=0; dp[i][1]=-1; }
68 k=sprintf(str,"%d",n);
69 for(s=1,i=1;i<k;i++){ s<<=1; s|=1; }
70 dfs(s,&next); // dp
71 printf("%d",makeNum(s)); next=dp[s][1];
72 while(next!=-1){
73 printf(" %d",makeNum(next));
74 next=dp[next][1];
75 }printf("\n");
76 }
77 return 0;
78}
79