]]>SPOJ 2154 Kruskalhttp://m.shnenglu.com/sdfond/archive/2010/02/06/107365.htmlsdfondsdfondSat, 06 Feb 2010 01:04:00 GMThttp://m.shnenglu.com/sdfond/archive/2010/02/06/107365.htmlhttp://m.shnenglu.com/sdfond/comments/107365.htmlhttp://m.shnenglu.com/sdfond/archive/2010/02/06/107365.html#Feedback0http://m.shnenglu.com/sdfond/comments/commentRss/107365.htmlhttp://m.shnenglu.com/sdfond/services/trackbacks/107365.html 猴子和Kruskal玩一个取矛_游戏Q给定n堆石子,n不大?00Q每堆石子的个数大于2于2 ^
32Q双方轮?hu)取子,每次可以从一堆中取最多k个,当一方取完石子后某堆矛_的个数是素数的话那么当前玩家莯。问猴子是否有必胜策略?br> 【题目分析?br> q是一道BT题,中间讄?jin)许多trick。开始对题意没有完全理解Q错?jin)很多次Q后来找来了(jin)数据Q才发现?jin)问题?br> 题目中描q的莯{略是:(x)"A
player wins if after his move the size of some heap is a prime
number."q句话乍一看以为是取完矛_后剩下的矛_个数是素数的时候就莯Q其实还隐藏着另一U可能:(x)如果多堆矛_个数是素敎ͼ当前玩家无论怎样取都能获胜,因ؓ(f)在他取完之后Q其他堆的石子个数是素数Q也满莯条g?br> 接下来考虑一般情c(din)这个题目是限制中间状态的Nim游戏Q也是_(d)对于一堆个Cؓ(f)n的石子而言Q它的SG值取决于于n的最大素数。注意这里题讑֏有了(jin)一个小trickQ题目说明了(jin)需要取1到k个,如果当前矛_个数本n是素敎ͼ当然是没用的Q因此是于n的最大素数。设于n的最大素数是p(题目中说明了(jin)矛_个数大于2Q因此p一定存?Q那么可以在k步以内到达p的一定是必胜态,而且是直接获胜,需要在输入的时候特?q一炚w要注意,在解决限制中间状态的Nim游戏时一般都需要特?。然后就是p
+ k + 1q个状态,因ؓ(f)它可辄状态全是必胜态,因此它是必|态,SGgؓ(f)0。现在考虑大于p + k + 1的状态,问题出来?jin)。以p + k +
2q个状态ؓ(f)例,因ؓ(f)它可以到达p + 2 ... p + k + 1q些状态,因ؓ(f)p + 2 ... p +
k都是直接莯状态,如何判定他们的SG值呢Q如果假讑֮们的SG值是1Q那么p + k +
2q个状态的SG值应该是2。但是思考一下SG值的定义Q它是定义在一个DAG上的Q所有的状态最后都是可以在有限步内转移到终止?必|?。但是p + 1 ...
p + kq些状态都转移C(jin)pq个状态上Q我们肯定不能认定p状态是l止态,因此仅仅凭借p + 1 ... p +
kq些状态是必胜态就单的把它们的SGD?是不恰当的;q些限制状态和以前的题目还?sh)同Q这些限制状态都不能转移到终止态上Q但是由于题目的要求Q它们又都是必胜态,因此把它们的SGD为无I大更合适些?br> 仔细思考一下带限制状态的SG游戏Q可以发玎ͼ它们和一般的SG游戏的区别在于,在分析一般的SG游戏的时候,对于一个状态图而言Q{Udl止态的时候ƈ不意味着游戏l束Q因为玩家可以通过走其他的状态图来保证是否达到必胜态;但是带限制状态的SG游戏Q限制的状态双斚w是不敢走的,因ؓ(f)一旦一方走入限制状态,另一方立刻获胜,游戏q止了(jin)。可以认为,只要走入限制态就相当于认输,对于双方玩家而言肯定都不?x)这样做Q因此这些限制状态就成了(jin)“ȝ?#8221;Q完全可以忽视这些状态(也就是说不存在到q些状态的转移Q。通过上述分析Q我们可以认定p
+ k +
2q个状态的SG值应该是1而不??br> 现在q个问题的做法就比较明朗?jin),对于每堆矛_Q去掉限制态的讨论后,变成了(jin)在集合{1...k}中选择元素的一个Subtraction
GameQ它的SG值是?k +
1)循环的?br> 然后是求最q素数的问题?sh)(jin),q个没有好办法,只能暴力枚D。对于一个数nQ在sqrt(n)到n之间存在素数Q感觉应该是Q但是不?x)证Q,因此最多枚举sqrt(n)ơ就能找到解。但是每ơ枚丑ֈ素的复杂度还是sqrt(n)Qd杂度q是比较高,我在本地跑数据跑?U,交上去超时了(jin)QSPOJ的时?0U,q居然也时Q数据够变态)(j)。想?jin)很久也没有什么新的算法,无奈只能在判素上下点功夫Q直接把Miller-Rabin搞出来了(jin)Q速度提高C(jin)2U,仍然时。后来又加了(jin)一些常C的优化,l于q了(jin)?br> 【ȝ?br> q个题目做了(jin)很长旉Q一斚w是审题(sh)清,错了(jin)几次Q另一斚w是对于SG的理论理解的不够透彻Q想?jin)很久终于想明白了(jin);再有是优化法也花了(jin)很长时间。不q通过q个题目对于SG理论的理解又q了(jin)一步,感觉不错Q呵c(din)?
#include <cstdio> #include <cmath> #include <algorithm> usingnamespace std; constint MOD =11, N =100001; int d[N], m[N]; int power_mod(int a, int b) { int ret =1, f = a; while (b) { if (b &1) ret = ret * f % MOD; f = f * f % MOD; b >>=1; } return ret; } void init() { int tmp; for (int i =2; i < N; i++) { tmp = (int)(ceil(i * log(i) / log(10.0) + 1e-2) + 1e-1); d[i] = tmp; m[i] = power_mod(i % MOD, i); } } int main() { char str[N*5]; int T, p, len, tmp; init(); scanf("%d", &T); while (T--) { scanf("%s", str); len = strlen(str); if (len ==1&& str[0] =='1') { puts("1"); continue; } p = lower_bound(d, d + N, len) - d; tmp =0; for (int i =0; i < len; i++) { tmp = tmp *10+ (str[i] -'0'); tmp = tmp % MOD; } printf("%d\n", tmp == m[p] ? p : -1); } return0; }
]]>TJU 3027 模线性方E组http://m.shnenglu.com/sdfond/archive/2009/03/22/77459.htmlsdfondsdfondSun, 22 Mar 2009 01:51:00 GMThttp://m.shnenglu.com/sdfond/archive/2009/03/22/77459.htmlhttp://m.shnenglu.com/sdfond/comments/77459.htmlhttp://m.shnenglu.com/sdfond/archive/2009/03/22/77459.html#Feedback0http://m.shnenglu.com/sdfond/comments/commentRss/77459.htmlhttp://m.shnenglu.com/sdfond/services/trackbacks/77459.html
TJU 3027 #include <cstdio> constint N =8; void extended_gcd(int a, int b, int&x, int&y) { if (!b) { x =1; y =0; return; } extended_gcd(b, a % b, x, y); int tmp = x; x = y; y = tmp - a / b * y; } int modular_linear_equation_system(int b[N], int m[N], int n) { int M =1, x, y, ret =0; for (int i =0; i < n; i++) M *= m[i]; for (int i =0; i < n; i++) { extended_gcd(M / m[i], m[i], x, y); ret += M / m[i] * x * b[i]; } while (ret <=0) ret += M; while (ret > M) ret -= M; return ret; } int main() { int m[N], b[N], T, n, tmp, ans; constint num =4, numc =3; char str[N], hash[30] =" ABCDEFGHIJKLMNOPQRSTUVWXYZ "; scanf("%d", &T); while (T--) { scanf("%d", &n); for (int i =0; i < num; i++) scanf("%d", &m[i]); for (int j =0; j < n; j++) { scanf("%d", &tmp); for (int i =1; i <= num; i++) { b[num-i] = tmp %100; tmp /=100; } ans = modular_linear_equation_system(b, m, num); for (int i =1; i <= numc; i++) { str[numc-i] = hash[ans%100]; ans /=100; } str[numc] ='\0'; if (j == n -1) { int k = numc -1; for (; k >=0; k--) if (str[k] !='') break; str[k+1] ='\0'; } printf("%s", str); } putchar('\n'); } return0; }
]]>HOJ 1356 —?Miller Rabin试http://m.shnenglu.com/sdfond/archive/2009/03/18/77069.htmlsdfondsdfondWed, 18 Mar 2009 13:15:00 GMThttp://m.shnenglu.com/sdfond/archive/2009/03/18/77069.htmlhttp://m.shnenglu.com/sdfond/comments/77069.htmlhttp://m.shnenglu.com/sdfond/archive/2009/03/18/77069.html#Feedback0http://m.shnenglu.com/sdfond/comments/commentRss/77069.htmlhttp://m.shnenglu.com/sdfond/services/trackbacks/77069.htmlMiller-RabinZ贚w定理:(x)如果(a, p) = 1Q那么a ^ (p - 1) = 1 mod p。满个性质的p叫伪素数Q如果一个数是伪素数Q那么它有很大可能是素数。通过多次的枚举aQ利用快速幂取模判断Q就可以知道p是不是素敎ͼMiller-Rabin试的成功率?/4?br>贚w定理是该定理的Ҏ(gu)形式Q如果p是素敎ͼ那么对于L整数aQa ^ p = a mod p。这个定理可以用归纳法证明,证明依据q样一个事实:(x)l合数C(n, k)是一个整敎ͼ如果n是素敎ͼ那么n和k!?n - k)!的每一w互素Q可以提出nQ也是C(n, k) / n也是整数Q所以n | C(n, k)?br>q个题目的代码如下:(x)
#include <cstdio> #include <stdlib.h> constint MAX =4, N =1000000; longlong PowerMod(longlong a, longlong b, longlong k) { longlong ret =1, f = a; while (b) { if (b &1) ret = ret * f % k; f = f * f % k; b >>=1; } return ret; } bool MillerRabin(longlong n) { int i; longlong tmp; srand(100); for (i =0; i < MAX; i++) { tmp = rand() % (n -1) +1; if (PowerMod(tmp, n -1, n) !=1) break; } return (i == MAX); } int main() { longlong n, i, j; bool tag[N] ={1, 1, 0}; for (i =2; i * i < N; i++) { if (tag[i]) continue; for (j = i; j * i < N; j++) tag[j*i] =1; } while (scanf("%lld", &n) ==1) { if (n < N) printf("%s\n", tag[n] ?"NO" : "YES"); else printf("%s\n", ((n &1) ==0) ||!MillerRabin(n) ?"NO" : "YES"); } return0; }
#include <cstdio> //ax + by = gcd(a, b) longlong extended_gcd(longlong a, longlong b, longlong&x, longlong&y) { longlong ret, tmp; if (!b) { x =1, y =0; return a; } ret = extended_gcd(b, a % b, x, y); tmp = x; x = y; y = tmp - a / b * y; return ret; } //ax = b mod n longlong modular_linear_equation(longlong a, longlong b, longlong n) { longlong x, y, e; longlong d = extended_gcd(a, n, x, y); if (b % d) return-1; e = b / d * x % n + n; return e % (n / d); } int main() { longlong a, b, c, ans; int k; while (scanf("%lld %lld %lld %d", &a, &b, &c, &k) ==4) { if (a ==0&& b ==0&& c ==0&& k ==0) break; ans = modular_linear_equation(c, b - a, 1LL << k); if (ans ==-1) puts("FOREVER"); else printf("%lld\n", ans); } return0; }
]]>{法求素?/title>http://m.shnenglu.com/sdfond/archive/2009/03/16/76775.htmlsdfondsdfondMon, 16 Mar 2009 13:29:00 GMThttp://m.shnenglu.com/sdfond/archive/2009/03/16/76775.htmlhttp://m.shnenglu.com/sdfond/comments/76775.htmlhttp://m.shnenglu.com/sdfond/archive/2009/03/16/76775.html#Feedback5http://m.shnenglu.com/sdfond/comments/commentRss/76775.htmlhttp://m.shnenglu.com/sdfond/services/trackbacks/76775.html
for (int i =2; i * i < N; i++) { if (tag[i]) continue; for (int j = i; i * j < N; j++) tag[i*j] =1; } for (int i =2; i < N; i++) if (!tag[i]) prime[tol++] = i;
]]>整数快速幂取模http://m.shnenglu.com/sdfond/archive/2009/03/15/76625.htmlsdfondsdfondSun, 15 Mar 2009 02:58:00 GMThttp://m.shnenglu.com/sdfond/archive/2009/03/15/76625.htmlhttp://m.shnenglu.com/sdfond/comments/76625.htmlhttp://m.shnenglu.com/sdfond/archive/2009/03/15/76625.html#Feedback4http://m.shnenglu.com/sdfond/comments/commentRss/76625.htmlhttp://m.shnenglu.com/sdfond/services/trackbacks/76625.htmluva 374 Big Mod
赤裸裸的整数快速幂取模
#include <cstdio>
longlong PowerMod(longlong a, int b, int k) { longlong tmp = a, ret =1; while (b) { if (b &1) ret = ret * tmp % k; tmp = tmp * tmp % k; b >>=1; } return ret; }