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 }
View Code
 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 }
View Code

 

posted on 2015-04-14 23:03  bai_yan  阅读(367)  评论(0编辑  收藏  举报

导航