疯狂的递推与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
(转载请注明出处)

浙公网安备 33010602011771号