SRM472

这次是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 };
View Code

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

 

code:

posted on 2014-03-26 20:16  yzcstc  阅读(173)  评论(0编辑  收藏  举报