在家都变的懒惰了,好久没写题解了,补补CF
模拟 A - Wet Shark and Odd and Even
#include <bits/stdc++.h> typedef long long ll; const int N = 1e5 + 5; const int INF = 0x3f3f3f3f; int main(void) { std::vector<int> vec; int n; scanf ("%d", &n); ll sum = 0; for (int x, i=1; i<=n; ++i) { scanf ("%d", &x); sum += x; if (x & 1) vec.push_back (x); } std::sort (vec.begin (), vec.end ()); int sz = vec.size (); if (sz > 0 && (sz & 1)) sum -= vec[0]; printf ("%I64d ", sum); return 0; }
开始想错了,当成斜率相等的。还好1000范围不大,统计矩阵每条对角线上的个数加点小优化就过了,代码丑。。。
#include <bits/stdc++.h> typedef long long ll; const int N = 2e5 + 5; bool vis[2][1005][1005]; int b[1005][1005]; std::pair<int, int> a[N]; ll cal(int x) { return 1ll * x * (x - 1) / 2; } int get_num1(int x, int y) { int xx = x, yy = y; int ret = 0; while (xx >= 1 && yy >= 1) { if (b[xx][yy]) ret++, vis[1][xx][yy] = true; xx--; yy--; } xx = x + 1, yy = y + 1; while (xx <= 1000 && yy <= 1000) { if (b[xx][yy]) ret++, vis[1][xx][yy] = true; xx++; yy++; } return ret; } int get_num0(int x, int y) { int xx = x, yy = y; int ret = 0; while (xx <= 1000 && yy >= 1) { if (b[xx][yy]) ret++, vis[0][xx][yy] = true; xx++; yy--; } xx = x - 1, yy = y + 1; while (xx >= 1 && yy <= 1000) { if (b[xx][yy]) ret++, vis[0][xx][yy] = true; xx--; yy++; } return ret; } int main(void) { int n; scanf ("%d", &n); for (int i=0; i<n; ++i) { scanf ("%d%d", &a[i].first, &a[i].second); b[a[i].first][a[i].second] = 1; } ll ans = 0; for (int i=0; i<n; ++i) { int x = a[i].first, y = a[i].second; if (!vis[0][x][y]) { ans += cal (get_num0 (x, y)); vis[0][x][y] = true; } if (!vis[1][x][y]) { ans += cal (get_num1 (x, y)); vis[1][x][y] = true; } } printf ("%I64d ", ans); return 0; }
E = sum (1000 * 乘积是p的倍数的概率)
#include <bits/stdc++.h> typedef long long ll; const int N = 1e5 + 5; const int EPS = 1e-8; int l[N], r[N]; double pos[N]; int main(void) { int n, p; scanf ("%d%d", &n, &p); for (int i=1; i<=n; ++i) { scanf ("%d%d", &l[i], &r[i]); pos[i] = 1.0 * (r[i] / p - ((l[i]-1) / p)) / (r[i] - l[i] + 1); } l[0] = l[n], r[0] = r[n], pos[0] = pos[n]; double ans = 0; for (int i=0; i<=n; ++i) { if (i < n) ans += pos[i] * 1.0 + (1.0 - pos[i]) * pos[i+1]; if (i > 0) ans += pos[i] * 1.0 + (1.0 - pos[i]) * pos[i-1]; } ans *= 1000; printf ("%.8f ", ans); return 0; }
数学(浮点) D - Rat Kwesh and Cheese
都取log,用long double,精度逆天!powl (): pow的long double版
C语言里对float类型数据的表示范围为-3.4*10^38~+3.4*10^38。double为-1.7*10^-308~1.7*10^308,long double为-1.2*10^-4932~1.2*10^4932.
类型 |
比特(位)数 |
有效数字 |
数值范围 |
float |
32 |
6~7 |
-3.4*10^38~+3.4*10^38 |
double |
64 |
15~16 |
-1.7*10^-308~1.7*10^308 |
long double |
128/ |
18~19 |
-1.2*10^-4932~1.2*10^4932 |
究竟如何计算该范围,分析如下:
对于单精度浮点数(float)来说,符号位一位,指数位8位,尾数23位。指数能够表示的指数范围为-128~127。尾数为23位。
#include <bits/stdc++.h> std::string ans[12] = { "x^y^z", "x^z^y", "(x^y)^z", "(x^z)^y", "y^x^z", "y^z^x", "(y^x)^z", "(y^z)^x", "z^x^y", "z^y^x", "(z^x)^y", "(z^y)^x" }; typedef long double ldouble; const double EPS = 1e-10; ldouble best; int id; bool better(ldouble val) { if (fabs (val - best) < EPS) return false; else if (best < val) { best = val; return true; } return false; } void try2(ldouble x, ldouble y, ldouble z, int pos) { //(x ^ y) ^ z ldouble val = z * y * log (x); if (better (val)) id = pos; } void try1(ldouble x, ldouble y, ldouble z, int pos) { //x ^ y ^ z ldouble val = powl (y, z) * log (x); if (better (val)) id = pos; } int main(void) { ldouble x, y, z; std::cin >> x >> y >> z; best = -1e12; id = -1; try1 (x, y, z, 0); try1 (x, z, y, 1); try2 (x, y, z, 2); try2 (x, z, y, 3); try1 (y, x, z, 4); try1 (y, z, x, 5); try2 (y, x, z, 6); try2 (y, z, x, 7); try1 (z, x, y, 8); try1 (z, y, x, 9); try2 (z, x, y, 10); try2 (z, y, x, 11); std::cout << ans[id] << ' '; return 0; }
数位DP(矩阵快速幂优化) E - Wet Shark and Blocks
题意:b组相同的n个数字,每组选择一个数字合并起来%x == k的方案数。
分析:dp思路,dp[i][(j*10+t)%x] += dp[i-1][j]。但是b太大了选择用矩阵快速幂优化,构造矩阵m[i][j]表示从i到j的方案数,答案就是m[0][k],那么base矩阵就是小于x的某个数字转移到根据给出n个数字转移到另一个数字y的方案数。
UPD:
寒假排位赛出了这题,又不会做。
构造x*x大小的矩阵,m[i][j]表示从i(%x)到j(%x)的方案数,状态转移用矩阵乘法:i->j1,j2,j3...->k => i->k
#include <bits/stdc++.h> using namespace std; typedef long long ll; typedef vector<ll> Vec; typedef vector<Vec> Mat; const int N = 5e4 + 5; const int MOD = 1e9 + 7; int cnt[10]; int n, b, k, x; void add_mod(ll &a, ll b) { a += b; if (a >= MOD) a -= MOD; } Mat matrix_mul(const Mat &A, const Mat &B) { Mat ret(A.size(), Vec(B[0].size())); for (int i=0; i<A.size(); ++i) for (int j=0; j<A[0].size(); ++j) if (A[i][j]) for (int k=0; k<B[0].size(); ++k) if (B[j][k]) add_mod(ret[i][k], A[i][j]*B[j][k]%MOD); return ret; } Mat matrix_pow(Mat X, int n) { Mat ret(X.size(), Vec(X.size())); for (int i=0; i<X.size(); ++i) ret[i][i] = 1; for (; n; n>>=1) { if (n & 1) ret = matrix_mul(ret, X); X = matrix_mul(X, X); } return ret; } int main() { scanf("%d%d%d%d", &n, &b, &k, &x); for (int i=1; i<=n; ++i) { int d; scanf("%d", &d); cnt[d]++; } Mat ans(100, Vec(100)); for (int i=0; i<x; ++i) { for (int j=1; j<=9; ++j) { ans[i][(i*10+j)%x] += cnt[j]; } } ans = matrix_pow(ans, b); printf("%I64d ", ans[0][k]); return 0; }