kb-01-e<取余操作,宽搜,巧妙>;
题目描述:
n属于1到200,找到对应的一个数只含有0和1,并且是n的倍数;
分析:
本题有几个数会是大数;所以要考虑大数;
用到余数的性质;例如n=6,1%6=1;
1*10%6=4; (1*10+1)%6=5;
4*10%6=4; (4*10+1)%6=5;
5*10%6=2; (5*10+1)%6=3;
(重复4,5)
2*10%6=2; 。。。。=3;
3*10%6=0;
这时候发现余数为0,说明这个数可以是6的倍数;倒退回去,数分别是1,10,11,100,101,110,111,。。。。1110;
可以发现余数是一样的,同余定理;
(a*b)%n = (a%n *b%n)%n
(a+b)%n = (a%n +b%n)%n
由同余模定理 (110*10+1)%6 = ((110*10)%6+1%6 )%6 = ((110%6 * 10%6)%6 +1 )%6;
用这个同余定理就可以解决大数问题了;然后就是记录路径,这里就是巧妙的地方;我还不太清除是怎么搞的,总之就是一共进行了k次操作,就相当于01全排列,首项是1,然后排到第一个符合的数的时候,这个数是第几个,它对应的二进制就是相应的串;这一题用bfs居然超时了;所以我打了个表,有一个不打表的做法;
代码如下:
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<queue> 6 using namespace std; 7 8 queue<int> q; 9 int n; 10 char a[205][200]={"1","10","111","100","10","1110","1001","1000","111111111","10","11","11100","1001","10010","1110","10000","11101","1111111110","11001","100","10101","110","110101","111000","100","10010","1101111111","100100","1101101","1110","111011","100000","111111","111010","10010","11111111100","111","110010","10101","1000","11111","101010","1101101","1100","1111111110","1101010","10011","1110000","1100001","100","100011","100100","100011","11011111110","110","1001000","11001","11011010","11011111","11100","100101","1110110","1111011111","1000000","10010","1111110","1101011","1110100","10000101","10010","10011","111111111000","10001","1110","11100","1100100","1001","101010","10010011","10000","1111111101","111110","101011","1010100","111010","11011010","11010111","11000","11010101","1111111110","1001","11010100","10000011","100110","110010","11100000","11100001","11000010","111111111111111111","100","101","1000110","11100001","1001000","101010","1000110","100010011","110111111100","1001010111","110","111","10010000","1011011","110010","1101010","110110100","10101111111","110111110","100111011","111000","11011","1001010","10001100111","11101100","1000","11110111110","11010011","10000000","100100001","10010","101001","11111100","11101111","11010110","11011111110","11101000","10001","100001010","110110101","100100","10011","100110","1001","1111111110000","11011010","100010","1100001","11100","110111","11100","1110001","11001000","10111110111","10010","1110110","1010100","10101101011","100100110","100011","100000","11101111","11111111010","1010111","1111100","1111110","1010110","11111011","10101000","10111101","111010","1111011111","110110100","1011001101","110101110","100100","110000","100101111","110101010","11010111","11111111100","1001111","10010","100101","110101000","1110","100000110","1001011","1001100","1010111010111","110010","11101111","111000000","11001","111000010","101010","110000100","1101000101","1111111111111111110","111000011","1000"}; 11 /* 12 int cou=0; 13 void bfs() 14 { 15 while(!q.empty()) 16 { 17 int t=q.front(); 18 q.pop(); 19 cou++; 20 if(t%n==0) 21 return; 22 q.push(t*10%n); 23 q.push((t*10+1)%n); 24 } 25 } 26 int main() 27 { 28 freopen("out","w",stdout); 29 for(int z=1;z<=200;z++) 30 { 31 n=z; 32 while(!q.empty()) 33 q.pop(); 34 memset(a,0,sizeof(a)); 35 cou=0; 36 a[0]=1; 37 q.push(1); 38 bfs(); 39 int i=0; 40 while(cou) 41 { 42 a[i++]=cou%2; 43 cou=cou/2; 44 } 45 printf("\""); 46 for(int j=i-1;j>=0;j--) 47 { 48 printf("%d",a[j]); 49 } 50 printf("\","); 51 } 52 return 0; 53 }*/ 54 55 int main() 56 { 57 while(cin>>n&&n) 58 { 59 printf("%s\n",a[n-1]); 60 } 61 return 0; 62 }
1 //Memory Time 2 //2236K 32MS 3 4 #include<iostream> 5 using namespace std; 6 7 int mod[524286]; //保存每次mod n的余数 8 //由于198的余数序列是最长的 9 //经过反复二分验证,436905是能存储198余数序列的最少空间 10 //但POJ肯定又越界测试了...524286是AC的最低下限,不然铁定RE 11 12 int main(int i) 13 { 14 int n; 15 while(cin>>n) 16 { 17 if(!n) 18 break; 19 20 mod[1]=1%n; //初始化,n倍数的最高位必是1 21 22 for(i=2;mod[i-1]!=0;i++) //利用同余模定理,从前一步的余数mod[i/2]得到下一步的余数mod[i] 23 mod[i]=(mod[i/2]*10+i%2)%n; 24 //mod[i/2]*10+i%2模拟了BFS的双入口搜索 25 //当i为偶数时,+0,即取当前位数字为0 。为奇数时,则+1,即取当前位数字为1 26 27 i--; 28 int pm=0; 29 while(i) 30 { 31 mod[pm++]=i%2; //把*10操作转化为%2操作,逆向求倍数的每一位数字 32 i/=2; 33 } 34 while(pm) 35 cout<<mod[--pm]; //倒序输出 36 cout<<endl; 37 } 38 return 0; 39 }