这次是rng_58出的题目,思维难度还是相当大的的。。很值得一做。
250pt:
题意:盒子里有n 个 potatoes,甲乙两个人,每次只能拿4的幂次方数(1,4,16...),最后不能拿的输。求谁赢
思路:打表找规律。结果是n%5 == 2 || n % 5 == 0 后者赢。否则先者。
code:
1 #line 7 "PotatoGame.cpp" 2 #include <cstdlib> 3 #include <cctype> 4 #include <cstring> 5 #include <cstdio> 6 #include <cmath> 7 #include <algorithm> 8 #include <vector> 9 #include <string> 10 #include <iostream> 11 #include <sstream> 12 #include <map> 13 #include <set> 14 #include <queue> 15 #include <stack> 16 #include <fstream> 17 #include <numeric> 18 #include <iomanip> 19 #include <bitset> 20 #include <list> 21 #include <stdexcept> 22 #include <functional> 23 #include <utility> 24 #include <ctime> 25 using namespace std; 26 27 #define PB push_back 28 #define MP make_pair 29 30 #define REP(i,n) for(i=0;i<(n);++i) 31 #define FOR(i,l,h) for(i=(l);i<=(h);++i) 32 #define FORD(i,h,l) for(i=(h);i>=(l);--i) 33 34 typedef vector<int> VI; 35 typedef vector<string> VS; 36 typedef vector<double> VD; 37 typedef long long LL; 38 typedef pair<int,int> PII; 39 int sg[15000]; 40 41 class PotatoGame 42 { 43 public: 44 string theWinner(int n) 45 { 46 if (n % 5 == 0 || n % 5 == 2) return "Hanako"; 47 return "Taro"; 48 } 49 };
500pt:
题意:有N<=50张卡片,每张卡片有正方两面,现在题目给定每张卡片的正反两面上的数字(数字为1~n,并且每个数字出现两次),现在求把这n张卡片拿去排列,有多少种结果
思路:需要知道的知识:
1、有重复数字的排列:n个数字排列,其中有a个数字出现两次,排列数为:n!/2^a
2、对于一个长度为n的置换,取出k个数出现2次,有2*C(n, k*2)方案。
当然,出现置换解题的关键当然就是他了。。
对于1张卡片,将两边的数字连一条边,那么所有的卡片就会出现若干个环(也就是置换啦)
那么对于不同的环之间,是不会互相影响的,直接用乘法原理统计
难点的就是相同环之间,我们就必须枚举出现相同的数的个数,然后结合1和2进行统计即可。对了还要用到乘法逆元。。具体见代码吧。
code:
1 #line 7 "TwoSidedCards.cpp" 2 #include <cstdlib> 3 #include <cctype> 4 #include <cstring> 5 #include <cstdio> 6 #include <cmath> 7 #include <algorithm> 8 #include <vector> 9 #include <string> 10 #include <iostream> 11 #include <sstream> 12 #include <map> 13 #include <set> 14 #include <queue> 15 #include <stack> 16 #include <fstream> 17 #include <numeric> 18 #include <iomanip> 19 #include <bitset> 20 #include <list> 21 #include <stdexcept> 22 #include <functional> 23 #include <utility> 24 #include <ctime> 25 using namespace std; 26 27 #define PB push_back 28 #define MP make_pair 29 30 #define REP(i,n) for(i=0;i<(n);++i) 31 #define FOR(i,l,h) for(i=(l);i<=(h);++i) 32 #define FORD(i,h,l) for(i=(h);i>=(l);--i) 33 #define M 1000000007 34 typedef vector<int> VI; 35 typedef vector<string> VS; 36 typedef vector<double> VD; 37 typedef long long LL; 38 typedef pair<int,int> PII; 39 long long dp[1200][50]; 40 long long C[120][120]; 41 int fa[50]; 42 43 class TwoSidedCards 44 { 45 public: 46 LL power(LL a, int b){ 47 LL ret = 1; 48 while (b){ 49 if (b & 1) ret = (ret * a) % M; 50 a = (a * a) % M; 51 b >>= 1; 52 } 53 return ret; 54 } 55 int find(int k){ 56 if (fa[k] == k) return k; 57 return fa[k] = find(fa[k]); 58 } 59 long long permCount(int n){ 60 LL ret = 0; 61 for (int i = 2; i <= n; i += 2) 62 ret = (ret + C[n][i] * power(power(2, i / 2 - 1), M - 2)) % M; 63 ret =(ret + C[n][0]) % M; 64 for (int i = 1; i <= n; ++i) 65 ret = (ret * i) % M; 66 return ret; 67 } 68 int theCount(vector <int> taro, vector <int> hanako) 69 { 70 for (int i = 0; i <= 50; ++i){ 71 C[i][0] = 1; 72 for (int j = 1; j <= i; ++j) C[i][j] = (C[i-1][j-1] + C[i-1][j]) % M; 73 } 74 int n = taro.size(), m = taro.size(); 75 for (int i = 0; i <= n; ++i) fa[i] = i; 76 for (int i = 0; i < n; ++i){ 77 int x = taro[i], y = hanako[i]; 78 int fx = find(x), fy = find(y); 79 if (fx != fy) fa[fx] = fy; 80 } 81 long long ret = 1; 82 for (int i = 1; i <= n; ++i) find(i); 83 for (int i = 1; i <= n; ++i) if (fa[i] == i){ 84 int s = 0; 85 for (int j = 1; j <= n; ++j) 86 if (fa[j] == i) ++s; 87 ret = (ret * C[m][s]) % M; 88 m -= s; 89 ret = (ret * permCount(s)) % M; 90 } 91 return ret; 92 } 93 };
code: