目录
Road To The 3rd Building · 期望
http://acm.hdu.edu.cn/showprobem.php?pid=6827
期望 = 区间的权值 * 区间出现的次数
当 n = 3 n=3 n=3
E ( x ) = ∑ x × p ( x ) = a 1 + 1 2 ( a 1 + a 2 ) + 1 3 ( a 1 + a 2 + a 3 ) + a 2 + 1 2 ( a 2 + a 3 ) + a 3 n ( n + 1 ) 2 E(x)=\sum x\times p(x)=\cfrac{ a_1+\frac{1}{2}(a_1+a_2)+\frac{1}{3}(a_1+a_2+a_3)+a_2+\frac{1}{2}(a_2+a_3)+a_3}{\cfrac{n(n+1)}{2}} E(x)=∑x×p(x)=2n(n+1)a1+21(a1+a2)+31(a1+a2+a3)+a2+21(a2+a3)+a3
= a 1 ( 1 + 1 2 + 1 3 ) + a 2 ( 1 + 2 1 2 + 1 3 ) + a 3 ( 1 + 1 2 + 1 3 ) 6 =\cfrac{a_1(1+\frac{1}{2}+\frac{1}{3})+a_2(1+2\frac{1}{2}+\frac{1}{3})+a_3(1+\frac{1}{2}+\frac{1}{3})}{6} =6a1(1+21+31)+a2(1+221+31)+a3(1+21+31)
当 n = 4 n=4 n=4
E ( x ) = a 1 + 1 2 ( a 1 + a 2 ) + 1 3 ( a 1 + a 2 + a 3 ) + 1 4 ( a 1 + a 2 + a 3 + a 4 ) + a 2 + 1 2 ( a 2 + a 3 ) + 1 3 ( a 2 + a 3 + a 4 ) + a 3 + 1 2 ( a 3 + a 4 ) + a 4 10 E(x)=\cfrac{ a_1+\frac{1}{2}(a_1+a_2)+\frac{1}{3}(a_1+a_2+a_3)+\frac{1}{4}(a_1+a_2+a_3+a_4)+a_2+\frac{1}{2}(a_2+a_3)+\frac{1}{3}(a_2+a_3+a_4)+a_3+\frac{1}{2}(a_3+a_4)+a_4}{10} E(x)=10a1+21(a1+a2)+31(a1+a2+a3)+41(a1+a2+a3+a4)+a2+21(a2+a3)+31(a2+a3+a4)+a3+21(a3+a4)+a4
= a 1 ( 1 + 1 2 + 1 3 + 1 4 ) + a 2 ( 1 + 2 1 2 + 2 1 3 + 1 4 ) + a 3 ( 1 + 2 1 2 + 2 1 3 + 1 4 ) + a 4 ( 1 + 1 2 + 1 3 + 1 4 ) 10 =\cfrac{a_1(1+\frac{1}{2}+\frac{1}{3}+\frac{1}{4})+a_2(1+2\frac{1}{2}+2\frac{1}{3}+\frac{1}{4})+a_3(1+2\frac{1}{2}+2\frac{1}{3}+\frac{1}{4})+a_4(1+\frac{1}{2}+\frac{1}{3}+\frac{1}{4})}{10} =10a1(1+21+31+41)+a2(1+221+231+41)+a3(1+221+231+41)+a4(1+21+31+41)
以此类推,当 n = 5 n=5 n=5
E ( x ) = a 1 ( 1 + 1 2 + 1 3 + 1 4 + 1 5 ) + a 2 ( 1 + 2 1 2 + 2 1 3 + 2 1 4 + 1 5 ) + a 3 ( 1 + 2 1 2 + 3 1 3 + 2 1 4 + 1 5 ) + a 4 ( 1 + 2 1 2 + 2 1 3 + 2 1 4 + 1 5 ) + a 5 ( 1 + 1 2 + 1 3 + 1 4 + 1 5 ) 15 E(x)=\cfrac{a_1(1+\frac{1}{2}+\frac{1}{3}+\frac{1}{4}+\frac{1}{5})+a_2(1+2\frac{1}{2}+2\frac{1}{3}+2\frac{1}{4}+\frac{1}{5})+a_3(1+2\frac{1}{2}+3\frac{1}{3}+2\frac{1}{4}+\frac{1}{5})+a_4(1+2\frac{1}{2}+2\frac{1}{3}+2\frac{1}{4}+\frac{1}{5}) +a_5(1+\frac{1}{2}+\frac{1}{3}+\frac{1}{4}+\frac{1}{5})}{15} E(x)=15a1(1+21+31+41+51)+a2(1+221+231+241+51)+a3(1+221+331+241+51)+a4(1+221+231+241+51)+a5(1+21+31+41+51)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
const int N = 1e6 + 10;
ll n;
ll qpow(ll a, ll b) {
a %= mod;
ll res = 1;
while (b) {
if (b & 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
ll Add(ll x, ll y) {
return (x + y) % mod;
}
ll Sub(ll x, ll y) {
return (x - y + mod) % mod;
}
ll Mul(ll x, ll y) {
return (x * y) % mod;
}
ll demo[N], sum[N], a[N];
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
for (int i = 1; i <= 200010; i++) {
demo[i] = qpow(i, mod - 2); // 1/i
sum[i] = Add(sum[i - 1], demo[i]); // ∑1/i
}
int T;
cin >> T;
while (T--) {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
ll tmp = 0;
ll res = 0;
for (int i = 1, j = n; i <= j; i++, j--) {
// tmp+= sum[j]-sum[i-1]
tmp = Add(tmp, Sub(sum[j], sum[i - 1]));
// res+=a[i] * tmp + a[n - i + 1] * tmp;
res = Add(res, Mul(a[i], tmp));
if (j > i) {
res = Add(res, Mul(a[j], tmp));
}
}
ll Inv = qpow(n * (n + 1) / 2, mod - 2); // 1/区间个数
res = Mul(res, Inv);
cout << res << endl;
}
return 0;
}
Little Rabbit’s Equation · 模拟
http://acm.hdu.edu.cn/showproblem.php?pid=6828
#include <bits/stdc++.h>
using namespace std;
#define between(x, a, b) (a<=x && x<=b)
typedef long long ll;
int bit[20];
string num1, num2, num3;
ll toInt(string s, int b) {
int sz = s.length();
for (int i = 0; i < sz; i++) {
bit[i] = (between(s[i], '0', '9') ? s[i] - '0' : s[i] - 'A' + 10);
}
ll res = 0;
for (int i = 0; i < sz; i++) {
if (bit[i] >= b) return -1; // 判断数字是否合法
res = res * b + bit[i];
}
return res;
}
bool solve(ll a, ll b, ll c, int op) {
if (op == 1) return (a + b) == c;
else if (op == 2) return (a - b) == c;
else if (op == 3) return (a * b) == c;
else return ((a % b) == 0 && (a / b == c)); // 防整除精度问题
}
bool check(int b, int op) {
ll x = toInt(num1, b);
if (x == -1) return false;
ll y = toInt(num2, b);
if (y == -1) return false;
ll z = toInt(num3, b);
if (z == -1) return false;
return solve(x, y, z, op);
}
string s;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
while (cin >> s) {
int sz = s.length();
int i = 0, j, op;
while (i < sz && (between(s[i], '0', '9') || between(s[i], 'A', 'F'))) i++;
num1 = s.substr(0, i);
if (s[i] == '+') op = 1;
else if (s[i] == '-') op = 2;
else if (s[i] == '*') op = 3;
else if (s[i] == '/') op = 4;
i++;
j = i;
while (i < sz && (between(s[i], '0', '9') || between(s[i], 'A', 'F'))) i++;
num2 = s.substr(j, i - j);
i++;
j = i;
while (i < sz && (between(s[i], '0', '9') || between(s[i], 'A', 'F'))) i++;
num3 = s.substr(j, i - j);
int f = -1;
for (int i = 2; i <= 16; i++) {
if (check(i, op)) {
f = i;
break;
}
}
cout << f << endl;
}
return 0;
}
Fragrant numbers · dp
http://acm.hdu.edu.cn/showproblem.php?pid=6831
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1e6 + 10;
int n;
int res[N];
string s = " 114514191911451419191145141919";
set<int> f[20][20];
void dfs(int l, int r) {
if (r - l + 1 <= 4) {
int num = 0;
for (int i = l; i <= r; i++) {
num = num * 10 + (s[i] - '0');
}
f[l][r].insert(num);
}
for (int i = l; i < r; i++) {
dfs(l, i);
dfs(i + 1, r);
for (int a: f[l][i]) {
for (int b: f[i + 1][r]) {
if (a + b <= 5000) {
f[l][r].insert(a + b);
}
if (a * b <= 5000) {
f[l][r].insert(a * b);
}
}
}
}
}
void init() {
dfs(1, 13);
memset(res, INF, sizeof res);
for (int i = 1; i <= 13; i++) {
for (int x:f[1][i]) {
res[x] = min(res[x], i);
}
}
for (int i = 1; i <= 5000; i++) {
if (res[i] == INF) res[i] = -1;
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
init();
int T;
cin >> T;
for (int cs = 1; cs <= T; cs++) {
cin >> n;
cout << res[n] << endl;
}
return 0;
}
A Very Easy Graph Problem · 树上任意两点间距离
http://acm.hdu.edu.cn/showproblem.php?pid=6832
官方题解
树上任意两点间距离的改版
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
const int N = 1e6 + 10;
struct Edge {
int v;
ll w;
};
vector<Edge> e[N];
int a[N];
int n, m;
int fa[N];
int find(int x) {
return fa[x] == x ? x : fa[x] = find(fa[x]);
}
void Union(int x, int y, ll w) {
int fx = find(x);
int fy = find(y);
if (fx == fy) return;
e[x].push_back({y, w});
e[y].push_back({x, w});
if (fx < fy) {
fa[fy] = fx;
} else {
fa[fx] = fy;
}
}
ll Mul(ll x, ll y) {
return (x * y) % mod;
}
ll Add(ll x, ll y) {
return (x + y) % mod;
}
ll Sub(ll x, ll y) {
return (x - y + mod) % mod;
}
ll res;
ll sum[N][2];
void dfs1(int u, int f) {
sum[u][0] = sum[u][1] = 0;
for (int i = 0, sz = e[u].size(); i < sz; i++) {
int v = e[u][i].v;
if (v != f) {
dfs1(v, u);
sum[u][0] += sum[v][0];
sum[u][1] += sum[v][1];
}
}
sum[u][a[u]]++;
}
void dfs2(int u, int f) {
for (int i = 0, sz = e[u].size(); i < sz; i++) {
int v = e[u][i].v;
if (v != f) {
dfs2(v, u);
res = Add(res, Mul(e[u][i].w, Mul(sum[v][0], Sub(sum[1][1], sum[v][1]))));
res = Add(res, Mul(e[u][i].w, Mul(sum[v][1], Sub(sum[1][0], sum[v][0]))));
}
}
}
ll p[N];
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
p[0] = 1;
for (int i = 1; i <= 200010; i++) {
p[i] = Mul(p[i - 1], 2);
}
int T, u, v;
cin >> T;
while (T--) {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> a[i];
// init
e[i].clear();
fa[i] = i;
}
for (int i = 1; i <= m; i++) {
cin >> u >> v;
Union(u, v, p[i]);
}
res = 0;
dfs1(1, 0);
dfs2(1, 0);
cout << res << endl;
}
return 0;
}
A Very Easy Math Problem
Yukikaze and Smooth numbers
Divisibility
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll b, x;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;
cin >> T;
while (T--) {
cin >> b >> x;
if (b % x == 1) {
cout << "T" << endl;
} else {
cout << "F" << endl;
}
}
return 0;
}
Expectation · 矩阵树求生成树个数
http://acm.hdu.edu.cn/showproblem.php?pid=6836
官方题解
E
(
∑
i
=
0
30
2
i
)
=
∑
i
=
0
30
E
(
2
i
)
=
∑
x
×
p
(
x
)
=
∑
i
=
0
30
2
i
×
p
(
2
i
)
=
∑
i
=
0
30
2
i
×
权
值
里
含
有
2
i
的
生
成
树
的
个
数
生
成
树
总
数
E(\sum_{i=0}^{30}2^i)=\sum_{i=0}^{30} E(2^i)=\sum x\times p(x)=\sum_{i=0}^{30} 2^i\times p(2^i)=\sum_{i=0}^{30}2^i\times \cfrac{权值里含有2^i的生成树的个数}{生成树总数}
E(i=0∑302i)=i=0∑30E(2i)=∑x×p(x)=i=0∑302i×p(2i)=i=0∑302i×生成树总数权值里含有2i的生成树的个数
若要让生成树的权值含有 2 i 2^i 2i ,显然生成树的每一条边的权值都要求含有 2 i 2^i 2i,
利用矩阵树定理再求一遍所有含有 2 i 2^i 2i 的边能构造出多少个生成树
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 998244353;
const int N = 1e2 + 10;
const int M = 1e5 + 10;
int n, m;
ll res = 0, sum = 0;
int arr[N][N]; // 基尔霍夫矩阵
vector<vector<int>> vec;// n-1阶行列式
struct edge {
int u, v, w;
} e[M];
ll Mul(ll a, ll b) {
return (a * b) % mod;
}
ll Add(ll a, ll b) {
return (a + b) % mod;
}
ll Sub(ll a, ll b) {
return (a - b + mod) % mod;
}
ll qpow(ll a, ll b) {
a %= mod;
ll res = 1;
while (b) {
if (b & 1)res = Mul(res, a);
b >>= 1;
a = Mul(a, a);
}
return res;
}
// 计算行列式的值
ll Determinant(const vector<vector<int>> &A) {
ll res = 1;
int n = A.size(), cnt = 0;
vector<vector<int>> B(n, vector<int>(n));
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
B[i][j] = A[i][j];
}
}
for (int i = 0; i < n; i++) {
int pivot = i;
for (int j = i; j < n; j++) {
if (abs(B[j][i]) > abs(B[pivot][i])) {
pivot = j;
}
}
if (i != pivot) {
swap(B[i], B[pivot]); // 交换两行
cnt ^= 1;
}
if (B[i][i] == 0) return 0;
ll val = qpow(B[i][i], mod - 2);
for (int j = i + 1; j < n; j++) {
ll coe = Mul(B[j][i], val);
for (int k = i; k < n; k++) {
B[j][k] = Sub(B[j][k], Mul(coe, B[i][k]));
}
}
}
for (int i = 0; i < n; i++) {
res = Mul(res, B[i][i]);
}
if (cnt) res = Sub(0, res);
return res;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int T;
cin >> T;
for (int cs = 1; cs <= T; cs++) {
sum = res = 0;
memset(arr, 0, sizeof arr);
vec.clear();
cin >> n >> m;
for (int i = 1; i <= m; i++) {
cin >> e[i].u >> e[i].v >> e[i].w;
}
for (int i = 1, u, v; i <= m; i++) {
u = e[i].u;
v = e[i].v;
// 构造基尔霍夫矩阵
arr[u][u]++, arr[v][v]++; // 增加度数
arr[u][v]--, arr[v][u]--; // 边数取反
}
// 取第一个n-1阶行列式
for (int i = 1; i < n; i++) {
vec.push_back({});
for (int j = 1; j < n; j++) {
vec[i - 1].push_back(arr[i][j]);
}
}
// 计算生成树的个数
sum = Determinant(vec);
for (int k = 0; k < 30; k++) {
memset(arr, 0, sizeof arr);
vec.clear();
for (int j = 1, u, v; j <= m; j++) {
u = e[j].u;
v = e[j].v;
if (e[j].w & (1ll << k)) {
arr[u][u]++, arr[v][v]++;
arr[u][v]--, arr[v][u]--;
}
}
for (int i = 1; i < n; i++) {
vec.push_back({});
for (int j = 1; j < n; j++) {
vec[i - 1].push_back(arr[i][j]);
}
}
ll ans = Determinant(vec);
if (!ans) continue;
res = Add(res, Mul(1ll << k, ans));
}
res = Mul(res, qpow(sum, mod - 2));
cout << res << endl;
}
return 0;
}