level 3 div1
要求会:exgcd 和组合重复计数 和一些trick
其实这题只有一个小小的trick,
考虑这样一个问题如果给你2个1和1个21个4求他们能组合成的所有数的和
共有12个数12=4!/(2!*1!*1!) 这个公式《组合数学》第3版上的重复计数上有
1124 1142 1214 1241 1412 1421 2114 2141 2411 4112 4121 4211你会发现每列1出现了6次,2是3次,4是3次有了这个规律就好做了,仔细分析一下,任何情况都会有相似的规律6:3:3=2:1:1 即2个1 1个2 1个4 6+3+3=12=4!/(2!*1!*1!)我们只需要枚举1 2 3 4 5 6 7 8 9 各出现多少次,然后o(1)就出解了。详细题解:https://apps.topcoder.com/wiki/display/tc/SRM+500(需要挂一个vpn)推荐——穹顶穿越。#include<iostream> #include<cstdio> #include<algorithm> #include<vector> #include<string> using namespace std; long long mod = 500500573; void exgcd(long long x, long long y, long long &rev, long long &temp) { if (y == 0)temp = 0, rev = 1; else { exgcd(y, x%y, temp, rev); temp -= (x / y)*rev; temp = temp%mod; } } long long J[3000], revJ[3000], m[3000]; void init() { J[0] = 1; long long temp = 0; m[0] = 1; revJ[0] = 1; for (int i = 1; i <= 2500; i++) { J[i] = i*J[i - 1] % mod; exgcd(J[i], mod, revJ[i], temp); revJ[i] = (revJ[i] + mod) % mod; m[i] = ((10 * m[i - 1])+1) % mod; } } class ProductAndSum { public: int getSum(int p2, int p3, int p5, int p7, int s) { long long temp; long long allans = 0; int d[11]; d[5] = p5; d[7] = p7; init(); for (d[6] = 0; d[6] <= min(p2, p3); d[6]++) { for (d[8] = 0; d[8] <= (p2 - d[6]) / 3 + 1; d[8]++) { for (d[4] = 0; d[4] <= (p2 - 3 * d[8] - d[6]) / 2 + 1; d[4]++) { for (d[9] = 0; d[9] <= (p3 - d[6]) / 2; d[9]++) { d[2] = p2 - 2 * d[4] - d[6] - 3 * d[8]; d[3] = p3 - d[6] - 2 * d[9]; d[1] = s - 2 * d[2] - 3 * d[3] - 4 * d[4] - 5 * d[5] - 6 * d[6] - 7 * d[7] - 8 * d[8] - 9 * d[9]; if (d[1] < 0 || d[2] < 0 || d[3] < 0)continue; long long lenth = 0; long long revlenth; for (int i = 1; i <= 9; i++)lenth += d[i]; exgcd(lenth, mod, revlenth, temp); revlenth = (revlenth + mod) % mod; long long k = J[lenth]; for (int i = 1; i <= 9; i++)k = (k*revJ[d[i]]) % mod; lenth--; long long ans = 0; for (int i = 1; i <= 9; i++) ans += d[i] * i; ans = (((((ans*k) % mod)*revlenth) % mod)*m[lenth]) % mod; allans += ans; } } } } allans = allans%mod; return (int)allans; } };
//一下代码仅用于测试: int main() { //long long q, p,mm; //mm = 11; //exgcd(3, mm, q, p); //cout << (q+mm)%mm << endl; ProductAndSum a; int p2, p3, p5, p7, s; scanf("%d%d%d%d%d", &p2, &p3, &p5, &p7, &s); int qq = a.getSum(p2, p3, p5, p7, s); cout << qq << endl; }
250:看代码秒懂然而题意很难懂。。。#include<iostream> #include<cstdio> #include<algorithm> #include<vector> #include<string> #include<queue> #include<functional> using namespace std; typedef pair<int, int>p; int vote[600]; class MafiaGame { public: priority_queue<p, vector<p>, greater<p>>que; double probabilityToLose(int N, vector<int> decisions) { double sum = 0; for (int i = 0; i < decisions.size(); i++) { vote[decisions[i]]++; } for (int i = 0; i < N; i++) que.push(p(vote[i], i)); for (int i = 1; i <= N- decisions.size(); i++) { p temp = que.top(); que.pop(); vote[temp.second]++; que.push(p(vote[temp.second], temp.second)); } int maxx = -1; for (int i = 0; i < N; i++) maxx = max(vote[i], maxx); for (int i = 0; i < N; i++) if (vote[i] == maxx)sum++; double temp = sum; if (sum == 1)return 1; else { while (1) { if (sum == 0)return 0; if (sum == 1)return 1 / temp; sum = N%(int)sum; } } } };