疯狂的递推与vijos1095 - 约瑟夫问题10E100版

 

  vijos训练中的这道题真的是非常非常难(对本人蒟蒻来说),花了一个晚上,仔细钻研题解[1]( ̄┰ ̄)~~,终于把这疯狂的递推给弄明白了……

  下面是一些记录及感想:

 

  首先,来一些疯狂的手写表:

                    20  21   22        23                             24

    n =    1   2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ...

    ans = 1   1 3 1 3 5 7 1 3 5   7   9  11 13 15 1   ...

  观察得:n每到2^x时,ans从1开始,每次递增2(即ans为奇数);

  则可以整理出一下思路:

      设f(x)=2^x

    1、找到p = f(0) + f(1) + f(2) + …… + f(i - 1) + f(i)   (a <= n 且 p + f(i + 1) > n)

    2、计算元素ans = (n - p) * 2 - 1

    

  以下是我的代码:

  1 //以下是C++代码
  2 
  3 #include<iostream>
  4 #include<string>
  5 #include<cstdio>
  6 using namespace std;
  7 
  8 //a数组存放n以及ans(后来n没用了)
  9 //b数组存放2^x
 10 //c数组存放上文所说的p
 11 //la、lb、lc存放a、b、c数组最后一位(最高位)下标
 12 string s;
 13 int a[103] = {0}, b[103] = {0}, c[103] = {0};
 14 int la(0), lb(0), lc(0);
 15 
 16 void jia(int *x, int *y, int &lx, int &ly);               //高精x += y
 17 void jian(int *x, int *y, int &lx, int &ly);              //高精x -= y(高精)
 18 void jian(int *x, int y, int &lx);                        //高精x -= y(y<10)
 19 void cheng(int *x, int &lx);                              //高精x *= 2
 20 bool xiaoyu(int *x, int *y, const int &lx, const int &ly);//高精x < y
 21 
 22 int main()
 23 {
 24     cin >> s;
 25     la = s.size() - 1;
 26     for (int i = 0; i != la + 1; ++i) a[la - i] = s[i] - 48;
 27     b[0] = 1; lb = 0;
 28     c[0] = 1; lc = 0;
 29     while (xiaoyu(c, a, lc, la))        //while (c < a)
 30     {
 31         cheng(b, lb);                   //b *= 2
 32         jia(c, b, lc, lb);              //c += b
 33     }
 34     jian(c, b, lc, lb);                 //c -= b
 35     jian(a, c, la, lc);                 //a -= c
 36     cheng(a, la);                       //a *= 2
 37     jian(a, 1, la);                     //a -= 1
 38     for (int i = la; i >= 0; --i) printf("%d", a[i]);
 39 }
 40 
 41 void jia(int *x, int *y, int &lx, int &ly)
 42 {
 43     if (lx < ly)  lx = ly;
 44     for(int i = 0; i <= lx; ++i)
 45     {
 46         x[i] += y[i];
 47         x[i + 1] += x[i] / 10;
 48         x[i] %= 10;
 49     }
 50     if (x[lx + 1] != 0) ++lx;
 51 }
 52 
 53 void jian(int *x, int *y, int &lx, int &ly)
 54 {
 55     for (int i = 0; i <= lx; ++i)
 56     {
 57         x[i] -= y[i];
 58         if (x[i] < 0) 
 59         {
 60             x[i] += 10;
 61             x[i + 1] -= 1;
 62         }
 63     }
 64     while (x[lx] == 0) --lx;
 65 }
 66 
 67 void jian(int *x, int y, int &lx)
 68 {
 69     x[0] -= y;
 70     int i = 0;
 71     while (x[i] < 0 && i <= lx)
 72     {
 73         x[i] += 10;
 74         x[i + 1] -= 1;
 75         ++i;
 76     }
 77     if (x[lx] == 0) --lx;
 78 }
 79 
 80 void cheng(int *x, int &lx)
 81 {
 82     int e(0);
 83     for(int i = 0; i <= lx; ++i)
 84     {
 85         x[i] = x[i] * 2 + e;
 86         e = x[i] / 10;
 87         x[i] %= 10;
 88     }
 89     if (e != 0) x[++lx] = e; 
 90 }
 91 
 92 bool xiaoyu(int *x, int *y, const int &lx, const int &ly)
 93 {
 94     if (lx < ly) return true;
 95     if (lx > ly) return false;
 96     for(int i = lx; i >= 0; --i)
 97     {
 98         if (x[i] < y[i]) return true;
 99         if (x[i] > y[i]) return false;
100     }
101     return false;
102 }

 

  注意:本题解代码中的高精为本人修改版本,专为本题定制,正统高精请自行学习。

 

  感想:疯狂的递推和疯狂的高精,特别特别……(无法用语言形容)。

 

  注释:

    [1]:我看的题解(和本人写的不同,但意思差不多),其中似乎还有一些其他约瑟夫问题的解法http://wiki.gimoo.net/view/10406.html

 

    

  (转载请注明出处)

posted @ 2017-03-12 22:58  天宇之翼  阅读(196)  评论(0)    收藏  举报