ADDED SRM/500/1A.cpp Index: SRM/500/1A.cpp ================================================================== --- SRM/500/1A.cpp +++ SRM/500/1A.cpp @@ -0,0 +1,100 @@ +#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> +#include <cstring> +using namespace std; +typedef long long LL; +typedef complex<double> CMP; + +class MafiaGame { public: + double probabilityToLose(int N, vector <int> decisions) + { + vector<int> vc; + { + map<int,int> voteCnt; + for(int i=0; i<decisions.size(); ++i) + voteCnt[decisions[i]] ++; + for(map<int,int>::iterator it=voteCnt.begin(); it!=voteCnt.end(); ++it) + vc.push_back( it->second ); + } + const int MAX = *max_element(vc.begin(), vc.end()); + if( MAX == 1 ) + return 0.0; + + const int GotMAX = count(vc.begin(), vc.end(), MAX); + for(int k=GotMAX; k; k=(N-k*MAX)%k) + if( k == 1 ) + return 1.0/GotMAX; + return 0.0; + } +}; + +// 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 double& Expected, const double& Received) { + bool ok = (abs(Expected - Received) < 1e-9); + 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(_, MafiaGame().probabilityToLose(N, decisions));} +int main(){ + +CASE(0) + int N = 3; + int decisions_[] = {1, 1, 1}; + vector <int> decisions(decisions_, decisions_+sizeof(decisions_)/sizeof(*decisions_)); + double _ = 1.0; +END +CASE(1) + int N = 5; + int decisions_[] = {1, 2, 3}; + vector <int> decisions(decisions_, decisions_+sizeof(decisions_)/sizeof(*decisions_)); + double _ = 0.0; +END +CASE(2) + int N = 20; + int decisions_[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 18, 19, 0}; + vector <int> decisions(decisions_, decisions_+sizeof(decisions_)/sizeof(*decisions_)); + double _ = 0.0; +END +CASE(3) + int N = 23; + int decisions_[] = {17, 10, 3, 14, 22, 5, 11, 10, 22, 3, 14, 5, 11, 17}; + vector <int> decisions(decisions_, decisions_+sizeof(decisions_)/sizeof(*decisions_)); + double _ = 0.14285714285714285; +END +/* +CASE(4) + int N = ; + int decisions_[] = ; + vector <int> decisions(decisions_, decisions_+sizeof(decisions_)/sizeof(*decisions_)); + double _ = ; +END +CASE(5) + int N = ; + int decisions_[] = ; + vector <int> decisions(decisions_, decisions_+sizeof(decisions_)/sizeof(*decisions_)); + double _ = ; +END +*/ +} +// END CUT HERE ADDED SRM/500/1B.cpp Index: SRM/500/1B.cpp ================================================================== --- SRM/500/1B.cpp +++ SRM/500/1B.cpp @@ -0,0 +1,112 @@ +#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> +#include <cstring> +using namespace std; +typedef long long LL; +typedef complex<double> CMP; + +class FractalPicture { public: + double getLength(int x1, int y1, int x2, int y2) + { + return rec(1, x1, y1, x2, y2); + } + + double rec(int i, int x1, int y1, int x2, int y2) + { + x1 = clip<-27,+27>(x1); + x2 = clip<-27,+27>(x2); + y1 = clip< 0,+81>(y1); + y2 = clip< 0,+81>(y2); + + if( i == 501 ) + return 0; + if( x1<=-27 && 27<=x2 && y1<=0 && 81<=y2 ) + return 81 + (500-i)*54; + if( x2<=-27 || 27<=x1 || y2<=0 || 81<=y1 ) + return 0; + double L0 = (x1<=0 && 0<=x2 ? clip<0,54>(y2)-clip<0,54>(y1) : 0); + x1=x1*3, x2=x2*3, y1=(y1-54)*3, y2=(y2-54)*3; + double L1 = rec(i+1, x1, y1, x2, y2); + double L2 = rec(i+1, y1, x1, y2, x2); + double L3 = rec(i+1, y1, -x2, y2, -x1); + return L0 + (L1+L2+L3)/3; + } + + template<int m, int M> + int clip(int v) { return max(m, min(v, M)); } +}; + +// 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 double& Expected, const double& Received) { + bool ok = (abs(Expected - Received) < 1e-9); + 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(_, FractalPicture().getLength(x1, y1, x2, y2));} +int main(){ + +CASE(0) + int x1 = -1; + int y1 = 0; + int x2 = 1; + int y2 = 53; + double _ = 53.0; +END +CASE(1) + int x1 = 1; + int y1 = 1; + int x2 = 10; + int y2 = 10; + double _ = 0.0; +END +CASE(2) + int x1 = -10; + int y1 = 54; + int x2 = 10; + int y2 = 55; + double _ = 21.0; +END +CASE(3) + int x1 = 14; + int y1 = 45; + int x2 = 22; + int y2 = 54; + double _ = 2999.0; +END +CASE(4) + int x1 = -28; + int y1 = 44; + int x2 = -16; + int y2 = 62; + double _ = 6992.0; +END +CASE(5) + int x1 = 0; + int y1 = 80; + int x2 = 1; + int y2 = 81; + double _ = 332; +END +} +// END CUT HERE ADDED SRM/500/1C.cpp Index: SRM/500/1C.cpp ================================================================== --- SRM/500/1C.cpp +++ SRM/500/1C.cpp @@ -0,0 +1,179 @@ +#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> +#include <cstring> +using namespace std; +typedef long long LL; +typedef complex<double> CMP; + +static const int MODVAL = 500500573; +struct mint +{ + int val; + mint():val(0){} + mint(int x):val(x%MODVAL) {} + mint(LL x):val(x%MODVAL) {} +}; +mint operator+(mint x, mint y) { return x.val+y.val; } +mint operator-(mint x, mint y) { return x.val-y.val+MODVAL; } +mint operator*(mint x, mint y) { return LL(x.val)*y.val; } +mint POW(mint x, int e) { + mint v = 1; + for(;e;x=x*x,e>>=1) + if(e&1) + v=v*x; + return v; +} +mint operator/(mint x, mint y) { return x * POW(y, MODVAL-2); } + +class ProductAndSum { public: + int getSum(int p2, int p3, int p5, int p7, int S) + { + // Precomputing n!, 1/n!, and 111...111 + vector<mint> FACT(2501), FACT_INV(2501), ONES(2501); + FACT[0] = FACT_INV[0] = 1; + ONES[0] = 0; + for(int n=1; n<FACT.size(); ++n) + { + FACT[n] = FACT[n-1] * n; + FACT_INV[n] = 1 / FACT[n]; + ONES[n] = ONES[n-1]*10 + 1; + } + + mint answer = 0; + + // Exhaustive search over the number of 4,6,8,9s : at most 33*50*50*100 < 8M iterations + for(int v8=0; v8*3<=p2; ++v8) + for(int v4=0; v4*2+v8*3<=p2; ++v4) + for(int v9=0; v9*2<=p3; ++v9) + for(int v6=0; v6+v4*2+v8*3<=p2 && v6+v9*2<=p3; ++v6) + { + // then, the number of 1,2,3s are computable + int v[] = {-1, -1, p2-v8*3-v4*2-v6, p3-v9*2-v6, v4, p5, v6, p7, v8, v9}; + { + int v1 = S; + for(int i=2; i<=9; ++i) + v1 -= i * v[i]; + if( v1 < 0 ) + continue; + v[1] = v1; + } + int N = accumulate(v+1, v+10, 0); + + // Now, let's compute the sum of all integers, who have N digits and #d = v[d], in constant time! + + // It can be calculated as follows: + // Q: how many of the integers have, say "1" in the last digit? + // A: it is, of course, C(N-1, v[1]-1, v[2], ..., v[9]) + // where C(k,a,b,..) is the # of ways of spliting k elements into groups of size a, b, ... + // So, the sum of the least digits of the integers are + // X = \Sigma_{d=1..9} (d * C(N-1, v[1], v[2], ..., v[d]-1, ..., v[9])) + // By the same argument, the sum of the second-last digits (10-no-kurai in japanese) is + // 10 * X + // For hundreds, the sum is 100*X, and so on. Eventualy, the sum of whole integers is + // t = (1+10+...+10^N) * X + // = 111...111 * \Sigma_{d=1..9} (d * C(N-1, v[1], v[2], ..., v[d]-1, ..., v[9])) + // Let us simplify the formula by using C(k,a,b,...) = k! / a!b!... + // t = 111...111 * \Sigma_{d=1..9} (d * (N-1)! / v[1]! / ... / v[9]! * v[d]) + // = 111...111 * (N-1)! / v[1]! / ... / v[9]! * \Sigma_{d=1..9} (d*v[d]) + // = 111...111 * (N-1)! / v[1]! / ... / v[9]! * S + // That's it! + + mint t = ONES[N] * FACT[N-1] * S; + for(int i=1; i<=9; ++i) + t = t * FACT_INV[v[i]]; + answer = answer + t; + } + return answer.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(_, ProductAndSum().getSum(p2, p3, p5, p7, S));} +int main(){ + +CASE(0) + int p2 = 2; + int p3 = 0; + int p5 = 0; + int p7 = 0; + int S = 4; + int _ = 26; +END +CASE(1) + int p2 = 0; + int p3 = 0; + int p5 = 0; + int p7 = 0; + int S = 10; + int _ = 110109965; +END +CASE(2) + int p2 = 2; + int p3 = 0; + int p5 = 0; + int p7 = 0; + int S = 5; + int _ = 610; +END +CASE(3) + int p2 = 1; + int p3 = 1; + int p5 = 1; + int p7 = 1; + int S = 10; + int _ = 0; +END +CASE(4) + int p2 = 5; + int p3 = 5; + int p5 = 5; + int p7 = 5; + int S = 100; + int _ = 61610122; +END +CASE(5) + int p2 = 100; + int p3 = 100; + int p5 = 100; + int p7 = 100; + int S = 2500; + int _ = -1; +END +/* +CASE(6) + int p2 = ; + int p3 = ; + int p5 = ; + int p7 = ; + int S = ; + int _ = ; +END +*/ +} +// END CUT HERE