ADDED SRM/566-U/1A.cpp Index: SRM/566-U/1A.cpp ================================================================== --- SRM/566-U/1A.cpp +++ SRM/566-U/1A.cpp @@ -0,0 +1,159 @@ +#include <iostream> +#include <sstream> +#include <iomanip> +#include <vector> +#include <string> +#include <map> +#include <set> +#include <algorithm> +#include <numeric> +#include <iterator> +#include <functional> +#include <complex> +#include <queue> +#include <stack> +#include <cmath> +#include <cassert> +using namespace std; +typedef long long LL; +typedef long double LD; +typedef complex<LD> CMP; + +LL comb(LL n, LL k) +{ + k = min(k, n-k); + + LL c = 1; + for(LL i=0; i<k; ++i) + c *= n-i, c /= i+1; + return c; +} + +class PenguinSledding { public: + long long countDesigns(int numCheckpoints, vector <int> checkpoint1, vector <int> checkpoint2) + { + LL zero = 1; + LL one = checkpoint1.size(); + LL star = 0; + LL triangle = 0; + + for(int center=1; center<=numCheckpoints; ++center) { + int leaf = 0; + for(int i=0; i<checkpoint1.size(); ++i) + if(checkpoint1[i] == center) + ++leaf; + else if(checkpoint2[i] == center) + ++leaf; + for(int k=2; k<=leaf; ++k) + star += comb(leaf, k); + } + + set< pair<int,int> > conn; + for(int i=0; i<checkpoint1.size(); ++i) { + conn.insert(make_pair(checkpoint1[i], checkpoint2[i])); + conn.insert(make_pair(checkpoint2[i], checkpoint1[i])); + } + for(int a=1; a<=numCheckpoints; ++a) + for(int b=a+1; b<=numCheckpoints; ++b) + for(int c=b+1; c<=numCheckpoints; ++c) + if(conn.count(make_pair(a,b)) && conn.count(make_pair(b,c)) && conn.count(make_pair(c,a))) + ++triangle; + + return zero + one + star + triangle; + } +}; + +// BEGIN CUT HERE +#include <ctime> +double start_time; string timer() + { ostringstream os; os << " (" << int((clock()-start_time)/CLOCKS_PER_SEC*1000) << " msec)"; return os.str(); } +template<typename T> ostream& operator<<(ostream& os, const vector<T>& v) + { os << "{ "; + for(typename vector<T>::const_iterator it=v.begin(); it!=v.end(); ++it) + os << '\"' << *it << '\"' << (it+1==v.end() ? "" : ", "); os << " }"; return os; } +void verify_case(const long long& Expected, const long long& Received) { + bool ok = (Expected == Received); + if(ok) cerr << "PASSED" << timer() << endl; else { cerr << "FAILED" << timer() << endl; + cerr << "\to: \"" << Expected << '\"' << endl << "\tx: \"" << Received << '\"' << endl; } } +#define CASE(N) {cerr << "Test Case #" << N << "..." << flush; start_time=clock(); +#define END verify_case(_, PenguinSledding().countDesigns(numCheckpoints, checkpoint1, checkpoint2));} +int main(){ + +CASE(0) + int numCheckpoints = 2; + int checkpoint1_[] = {1}; + vector <int> checkpoint1(checkpoint1_, checkpoint1_+sizeof(checkpoint1_)/sizeof(*checkpoint1_)); + int checkpoint2_[] = {2}; + vector <int> checkpoint2(checkpoint2_, checkpoint2_+sizeof(checkpoint2_)/sizeof(*checkpoint2_)); + long long _ = 2LL; +END +CASE(1) + int numCheckpoints = 4; + int checkpoint1_[] = {1,2,3}; + vector <int> checkpoint1(checkpoint1_, checkpoint1_+sizeof(checkpoint1_)/sizeof(*checkpoint1_)); + int checkpoint2_[] = {2,3,4}; + vector <int> checkpoint2(checkpoint2_, checkpoint2_+sizeof(checkpoint2_)/sizeof(*checkpoint2_)); + long long _ = 6LL; +END +CASE(2) + int numCheckpoints = 6; + int checkpoint1_[] = {1,3,6}; + vector <int> checkpoint1(checkpoint1_, checkpoint1_+sizeof(checkpoint1_)/sizeof(*checkpoint1_)); + int checkpoint2_[] = {2,4,4}; + vector <int> checkpoint2(checkpoint2_, checkpoint2_+sizeof(checkpoint2_)/sizeof(*checkpoint2_)); + long long _ = 5LL; +END +CASE(3) + int numCheckpoints = 50; + int checkpoint1_[] = {40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 50, 40, 40, 40, + 23, 4, 24, 40, 22, 40, 8, 40, 40, + 40, 34, 21, 40, 40, 38, 40, 40, + 40, 40, 40, 28, 40, 40, 40, 40, + 46, 13, 40, 40, 40, 47, 40, 40}; + vector <int> checkpoint1(checkpoint1_, checkpoint1_+sizeof(checkpoint1_)/sizeof(*checkpoint1_)); + int checkpoint2_[] = {45, 42, 20, 48, 12, 32, 25, 10, + 26, 39, 16, 2, 19, 43, 37, 17, + 19, 19, 19, 18, 19, 27, 19, 29, + 11, 36, 19, 19, 1, 41, 19, 35, + 14, 33, 49, 3, 19, 7, 5, 19, 31, + 19, 19, 6, 9, 15, 19, 44, 30}; + vector <int> checkpoint2(checkpoint2_, checkpoint2_+sizeof(checkpoint2_)/sizeof(*checkpoint2_)); + long long _ = 68719493118LL; +END +CASE(4) + int numCheckpoints = 36; + int checkpoint1_[] = {13, 24, 24, 20, 31, 16, 10, 36, 34, 32, + 28, 5, 20, 29, 23, 2, 14, 4, 9, 5, 19, + 21, 8, 1, 26, 27, 25, 15, 22, 30, 30, + 6, 11, 7, 2, 35, 13, 29, 4, 12, 33, 18, + 13, 14, 17, 35, 3}; + vector <int> checkpoint1(checkpoint1_, checkpoint1_+sizeof(checkpoint1_)/sizeof(*checkpoint1_)); + int checkpoint2_[] = {10, 15, 27, 1, 29, 11, 5, 18, 33, 1, 9, + 2, 31, 6, 19, 10, 33, 18, 6, 27, 3, 22, + 4, 12, 31, 30, 34, 16, 7, 24, 3, 28, 15, + 21, 22, 8, 26, 20, 14, 32, 25, 17, 35, + 8, 36, 26, 23}; + vector <int> checkpoint2(checkpoint2_, checkpoint2_+sizeof(checkpoint2_)/sizeof(*checkpoint2_)); + long long _ = 162LL; +END +/* +CASE(5) + int numCheckpoints = ; + int checkpoint1_[] = ; + vector <int> checkpoint1(checkpoint1_, checkpoint1_+sizeof(checkpoint1_)/sizeof(*checkpoint1_)); + int checkpoint2_[] = ; + vector <int> checkpoint2(checkpoint2_, checkpoint2_+sizeof(checkpoint2_)/sizeof(*checkpoint2_)); + long long _ = LL; +END +CASE(6) + int numCheckpoints = ; + int checkpoint1_[] = ; + vector <int> checkpoint1(checkpoint1_, checkpoint1_+sizeof(checkpoint1_)/sizeof(*checkpoint1_)); + int checkpoint2_[] = ; + vector <int> checkpoint2(checkpoint2_, checkpoint2_+sizeof(checkpoint2_)/sizeof(*checkpoint2_)); + long long _ = LL; +END +*/ +} +// END CUT HERE ADDED SRM/566-U/1B.cpp Index: SRM/566-U/1B.cpp ================================================================== --- SRM/566-U/1B.cpp +++ SRM/566-U/1B.cpp @@ -0,0 +1,155 @@ +#include <iostream> +#include <sstream> +#include <iomanip> +#include <vector> +#include <string> +#include <map> +#include <set> +#include <algorithm> +#include <numeric> +#include <iterator> +#include <functional> +#include <complex> +#include <queue> +#include <stack> +#include <cmath> +#include <cassert> +using namespace std; +typedef long long LL; +typedef long double LD; +typedef complex<LD> CMP; + +static const unsigned MODVAL = 1000000007; +struct mint +{ + unsigned val; + mint():val(0){} + mint(int x):val(x%MODVAL) {} + mint(unsigned x):val(x%MODVAL) {} + mint(LL x):val(x%MODVAL) {} +}; +mint& operator+=(mint& x, mint y) { return x = x.val+y.val; } +mint& operator*=(mint& x, mint y) { return x = LL(x.val)*y.val; } +mint operator+(mint x, mint y) { return x+=y; } +mint operator*(mint x, mint y) { return x*=y; } + +template<typename T> +vector<T> MATMULxx(const vector<T>& a, const vector<T>& v) +{ + int N = a.size(); + vector<T> u(N); + for(int i=0; i<N; ++i) + for(int j=0; j<N; ++j) + u[i] += a[(j-i+N)%N]*v[j]; + return u; +} + +template<typename T> +vector<T> MATMULxx(const vector<T>& a) +{ + int N = a.size(); + vector<T> c(N); + for(int j=0; j<N; ++j) + for(int k=0; k<N; ++k) + c[j] += a[k]*a[(j-k+N)%N]; + return c; +} + +template<typename T> +vector<T> MATPOWMULxx(vector<T> a, LL e, vector<T> v) +{ + for(; e; e>>=1, a=MATMULxx(a)) + if(e&1) + v = MATMULxx(a, v); + return v; +} + +class PenguinEmperor { public: + int countJourneys(int N, long long daysPassed) + { + vector<mint> v(N), u(N); + u[0] = 1; + for(int i=0; i<N; ++i) { + if(i == daysPassed % N) + v = u; + vector<mint> uu(N); + for(int x=0; x<N; ++x) { + int f = (x+i+1)%N; + int b = (x-i-1+N)%N; + uu[x] += u[f]; + if(f!=b) + uu[x] += u[b]; + } + u = uu; + } + + v = MATPOWMULxx(u, daysPassed/N, v); + return v[0].val; + } +}; + +// BEGIN CUT HERE +#include <ctime> +double start_time; string timer() + { ostringstream os; os << " (" << int((clock()-start_time)/CLOCKS_PER_SEC*1000) << " msec)"; return os.str(); } +template<typename T> ostream& operator<<(ostream& os, const vector<T>& v) + { os << "{ "; + for(typename vector<T>::const_iterator it=v.begin(); it!=v.end(); ++it) + os << '\"' << *it << '\"' << (it+1==v.end() ? "" : ", "); os << " }"; return os; } +void verify_case(const int& Expected, const int& Received) { + bool ok = (Expected == Received); + if(ok) cerr << "PASSED" << timer() << endl; else { cerr << "FAILED" << timer() << endl; + cerr << "\to: \"" << Expected << '\"' << endl << "\tx: \"" << Received << '\"' << endl; } } +#define CASE(N) {cerr << "Test Case #" << N << "..." << flush; start_time=clock(); +#define END verify_case(_, PenguinEmperor().countJourneys(numCities, daysPassed));} +int main(){ + +CASE(0) + int numCities = 3; + long long daysPassed = 2LL; + int _ = 2; +END +CASE(1) + int numCities = 4; + long long daysPassed = 3LL; + int _ = 2; +END +CASE(2) + int numCities = 5; + long long daysPassed = 36LL; + int _ = 107374182; +END +CASE(3) + int numCities = 300; + long long daysPassed = 751LL; + int _ = 413521250; +END +CASE(4) + int numCities = 300; + long long daysPassed = 750LL; + int _ = 0; +END +CASE(5) + int numCities = 350; + long long daysPassed = 1000000000000000000LL; + int _ = 667009739; +END +CASE(6) + int numCities = 5; + long long daysPassed = 7LL; + int _ = 12; +END +/* +CASE(7) + int numCities = ; + long long daysPassed = LL; + int _ = ; +END +CASE(8) + int numCities = ; + long long daysPassed = LL; + int _ = ; +END +*/ +} +// END CUT HERE Index: lib/doc/nim.txt ================================================================== --- lib/doc/nim.txt +++ lib/doc/nim.txt @@ -58,11 +58,16 @@ - *n1 + *n2 = *(n1 xor n2) - より一般的に G1≡*n1, G2≡*n2 ならば、G1 + G2 ≡ *(n1 xor n2) 証明 - *n1 + *n2 + *(n1 xor n2) が必敗であることを言えば良い。 - + - (n1 xor n2 xor (n1 xor n2)) は 0 である + - 一手動かすと 0 じゃなくなる + >> n1 と n2 と n1^n2 のどれか一個だけビットが変わるので絶対xorが変わるから + - 相手は一手動かして 0 に戻せる + >> 常に + - よって最終局面"全部 0"になるのは絶対に自分のターン ------------------------------------------------------------------------------------------- 定理【ゲームの状態遷移はmex】 - {*n1, ..., *nk} ≡ *mex(n1,...,nk)