srm 565 div2
1、水题,简单的画图,略过。
2、用到了贪心算法,需要把当前n个金币可以买到的最强能力保存下来,然后在可以达到终点的路径中取最小的即可。
1 #include <iostream> 2 #include <string> 3 #include <vector> 4 #include <cstdlib> 5 #include <cmath> 6 #include <map> 7 #include <stack> 8 #include <algorithm> 9 #include <list> 10 #include <ctime> 11 #include <set> 12 #include <queue> 13 using namespace std; 14 15 typedef long long ll; 16 ll pricepower[30][50]; 17 class MonstersValley2 { 18 public: 19 int minimumPrice(vector<int> dread, vector<int> price) { 20 int dsz = dread.size(); 21 pricepower[0][price[0]] = dread[0]; 22 for (int i = 1; i < dsz; i++) { 23 for (int j = 45; j >= -1; j--) { 24 if (pricepower[i - 1][j] >= dread[i]) { 25 pricepower[i][j] = pricepower[i - 1][j]; 26 } 27 } 28 29 for (int j = 45; j >= -1; j--) { 30 if (pricepower[i-1][j]!=0) { 31 pricepower[i][j+price[i]] = max(pricepower[i][j+price[i]],pricepower[i - 1][j]+dread[i]); 32 } 33 } 34 } 35 int res=0; 36 for (int i = 0; i < 45; i++) { 37 if(pricepower[dsz-1][i]!=0){ 38 res=i; 39 break; 40 } 41 } 42 return res; 43 } 44 45 };
3、刚开始想到的办法是因子a到N的路径,时间复杂度太高了,N的因子个数是n,时间复杂度是O(H*n^2),后来发现矩阵相乘的时候可以优化,但是n的复杂度又上去了,达到O(log(H)*n^3)(下边),超过了两秒,还是不行。
1 #include <iostream> 2 #include <string> 3 #include <vector> 4 #include <cstdlib> 5 #include <map> 6 #include <algorithm> 7 #include <stack> 8 #include <queue> 9 #include <cmath> 10 using namespace std; 11 const int mool = 1000000009; 12 typedef long long ll; 13 typedef vector<vector<int> > vvint; 14 typedef map<int, int>::iterator it_int_int; 15 typedef map<int, int> mii; 16 map<int, int> allmap; 17 class DivisibleSequence { 18 public: 19 int count(int N, int H) { 20 if (H == 1) 21 return 1; 22 int half = sqrt(N) + 10; 23 cout << half << endl; 24 int cur = N; 25 vector<int> div; 26 div.push_back(1); 27 div.push_back(N); 28 for (int i = 2; i < half; i++) { 29 if ((cur % i) == 0) { 30 while (1) { 31 div.push_back(i); 32 cur = cur / i; 33 if ((cur % i) != 0) 34 break; 35 } 36 } 37 } 38 if (cur != 1 && cur != N) 39 div.push_back(cur); 40 map<int, int> num_c; 41 for (int i = 0; i < div.size(); i++) 42 num_c[div[i]]++; 43 map<int, int> num_next; 44 num_next = num_c; 45 for (it_int_int j = num_next.begin(); num_next.end() != j; j++) { 46 j->second = 1; 47 } 48 while (1) { 49 bool judge = true; 50 for (it_int_int i = num_c.begin(); num_c.end() != i; i++) { 51 for (it_int_int j = num_next.begin(); num_next.end() != j; 52 j++) { 53 ll cnum = j->first; 54 ll mul = (i->first) * cnum; 55 if ((N % mul) == 0) { 56 it_int_int ittmp = num_next.find(mul); 57 if (num_next.end() == ittmp) { 58 judge = false; 59 num_next[mul] = 1; 60 } 61 } 62 } 63 } 64 if (judge) 65 break; 66 } 67 68 int tmpkaka = 0; 69 for (it_int_int j = num_next.begin(); num_next.end() != j; j++) { 70 allmap[tmpkaka] = j->first; 71 cout << allmap[tmpkaka] << endl; 72 tmpkaka++; 73 } 74 int nsz = num_next.size(); 75 cout << nsz << endl; 76 vector<vector<int> > allzero(nsz, vector<int>(nsz, 0)); 77 78 vvint pow = allzero; 79 int i1 = 0; 80 for (it_int_int i = num_next.begin(); num_next.end() != i; i++) { 81 int cur_nm1 = i->first; 82 int j1 = 0; 83 for (it_int_int j = num_next.begin(); num_next.end() != j; j++) { 84 int cur_nm = j->first; 85 if ((cur_nm % cur_nm1) == 0) { 86 ll tmp = (pow[i1][j1] + i->second) % mool; 87 pow[i1][j1] = tmp; 88 } 89 j1++; 90 } 91 i1++; 92 } 93 94 vvint a, c, res; 95 a = pow; 96 res = allzero; 97 for (int i = 0; i < nsz; i++) { 98 res[i][i] = 1; 99 } 100 int counter = H - 1; 101 int kaka = 0; 102 while (counter) { 103 cout << kaka << endl; 104 int remain = counter % 2; 105 cout << "here2\n"; 106 if (remain == 1) { 107 multi(pow, res, res); 108 } 109 cout << "here\n"; 110 counter /= 2; 111 multi(a, a, pow); 112 113 cout << "here1\n"; 114 a = pow; 115 kaka++; 116 } 117 int finalres = 0; 118 for (int i = 0; i < nsz; i++) { 119 finalres = (finalres + res[i][nsz - 1]) % mool; 120 } 121 return finalres; 122 } 123 void multi(vvint& a, vvint b, vvint &c) { 124 int asz = a.size(); 125 for (int i = 0; i < asz; i++) { 126 for (int j = i; j < asz; j++) { 127 if ((allmap[j] % allmap[i]) == 0) { 128 c[i][j] = 0; 129 for (int k = i; k < j + 1; k++) { 130 if (a[i][k] != 0 && b[k][j] != 0) { 131 ll tmp1 = a[i][k]; 132 ll tmp2 = b[k][j]; 133 ll tmp3 = c[i][j]; 134 ll curval = (tmp3 + tmp1 * tmp2) % mool; 135 c[i][j] = curval; 136 } 137 } 138 } 139 } 140 } 141 } 142 };
今天看了看wiki,终于知道怎么办了,还是数学功底要深厚啊,费马小定理啊~~~泪奔,实在想不到
1 #include <iostream> 2 #include <string> 3 #include <vector> 4 #include <cstdlib> 5 #include <map> 6 #include <algorithm> 7 #include <stack> 8 #include <queue> 9 #include <cmath> 10 using namespace std; 11 12 typedef long long ll; 13 const ll mod = 1000000009; 14 15 class DivisibleSequence { 16 public: 17 ll modPow(ll x, ll y) { //计算x的y次方 18 ll r = 1, a = x; 19 while (y > 0) { 20 if ((y & 1) == 1) { 21 r = (r * a) % mod; 22 } 23 a = (a * a) % mod; 24 y /= 2; 25 } 26 return r; 27 } 28 ll modInverse(ll x) { 29 //计算x',使得 x * x' =1 (模 mod),mod是质数,可知 x * (x^(mod-2)) =1 (模 mod) 30 //可得x'=(x^(mod-2)) (模 mod) 31 return modPow(x, mod - 2); 32 } 33 34 ll modDivision(ll p, ll q) { 35 //若想计算 x/y (模mod),等价于计算 x*y' (模mod) 36 return (p * modInverse(q)) % mod; 37 } 38 39 ll C(ll n, int k) { //计算C(n,k) 40 if (k > n) { 41 return 0; 42 } 43 ll p = 1, q = 1; 44 for (int i = 1; i <= k; i++) { 45 q = (q * i) % mod; 46 p = (p * (n - i + 1)) % mod; 47 } 48 return modDivision(p, q); 49 } 50 int count(int N, int H) { 51 ll res = 1; 52 //获取质因子p以及它的幂c 53 for (int p = 2; p <= N / p; p++) { 54 int c = 0; 55 while (N % p == 0) { 56 N /= p; 57 c++; 58 } 59 res = (res * C(H - 1 + c, c)) % mod; 60 } 61 62 if (N > 1) {//如果还剩下一个质数因子 63 res = (res * C(H, 1)) % mod; 64 } 65 return (int) res; 66 } 67 };
div1-2
nim游戏的变种,同构映射加速部分蛮有意思。
1 #include <iostream> 2 #include <string> 3 #include <vector> 4 #include <cstdlib> 5 #include <map> 6 #include <algorithm> 7 #include <stack> 8 #include <queue> 9 #include <cmath> 10 using namespace std; 11 12 typedef long long ll; 13 typedef vector<int> vi; 14 typedef vector<long long> vll; 15 const ll mod = 1000000009; 16 class TheDivisionGame { 17 public: 18 ll countWinningIntervals(int L, int R) { 19 int n = R - L + 1; 20 // Find the list of n counts of prime factors: 21 vi nimber(n); 22 vi current(n); 23 for (int i = L; i <= R; i++) { 24 current[i - L] = i; 25 } 26 // A modified Sieve of Erathostenes: 27 for (int p = 2; p <= R / p; p++) { 28 int s = L; 29 if (L % p != 0) { 30 s += p - (L % p); 31 } 32 while (s <= R) { 33 while (current[s - L] % p == 0) { 34 current[s - L] /= p; 35 nimber[s - L]++; 36 } 37 s += p; 38 } 39 } 40 for (int i = L; i <= R; i++) { 41 if (current[i - L] != 1) { 42 nimber[i - L]++; 43 } 44 } 45 for (int i = L; i <= R; i++) { 46 cout << nimber[i - L] << " "; 47 } 48 cout << endl; 49 50 // Counting the number of consecutive subsequences with a xor different 51 // to 0. 52 ll s = 0; //We will first count the ones with a xor equal to 0: 53 54 // The following two codes are equivalent. Can you tell why? 55 // #1: 56 vll next(32); 57 for (int i = n - 1; i >= 0; i--) { 58 vll curr(32); 59 for (int x = 0; x < 32; x++) { 60 curr[nimber[i] ^ x] = next[x]; //等价于curr[x] = next[nimber[i] ^x]; 61 } //1 62 curr[nimber[i]]++; //2 63 s += curr[0]; 64 next = curr; 65 } 66 67 //方法1.5 68 // vll origin(32); 69 // ll fmap = nimber[n - 1]; 70 // for (int i = n - 1; i >= 0; i--) { 71 // origin[0 ^ fmap]++; 72 // fmap ^= nimber[i]; 73 // s += origin[fmap]; 74 // } 75 76 //方法2 77 /* ll dp(32, 0); 78 int x = 0; 79 for (int i = n - 1; i >= 0; i--) { 80 dp[x]++; 81 x ^= nimber[i]; 82 s += dp[x]; 83 }*/ 84 85 return (n + 1) * (ll) n / 2 - s; 86 } 87 };