考場上想了一個 m^3 * n 的 DP
表示到 i 最後一個是j,出現了k次,衆數爲l的方案數
用前綴和優化轉移可以做到 m^3 * n
最主要的瓶頸還是在 n,我們用類似離散化的思想,將1–siz 填進去
最後乘上一個 就是答案
於是有 m^4 的做法,可以得50分
考慮求出衆數 <= k的答案 然後減去
仍然 DP , 表示到第i位,當前數爲 j
但是有不合法的,於是有
#include<bits/stdc++.h>
#define N 255
using namespace std;
const int Mod = 1000000007;
typedef long double ld;
ld f[N][N], c[N], p[N]; int T, m, n;
int read(){
int cnt = 0, f = 1; char ch = 0;
while(!isdigit(ch)){ ch = getchar(); if(ch == '-')f = -1;}
while(isdigit(ch)){ cnt = cnt*10 + (ch-'0'), ch = getchar();}
return cnt * f;
}
int main(){
T = read();
while(T--){
m = read(), n = read(); c[0] = 1;
for(int i = 1; i <= m; i++) c[i] = c[i-1] * (n - i + 1) / i;
ld ans = 0;
memset(p, 0, sizeof(p));
for(int k = 1; k <= m; k++){
memset(f, 0, sizeof(f)); f[0][0] = 1;
for(int i = 1; i <= m; i++){
for(int j = 1; j <= i; j++){
f[i][j] = f[i-1][j] + f[i-1][j-1];
if(i - k - 1 >= 0) f[i][j] -= f[i-k-1][j-1];
}
}
for(int i = 0; i <= m; i++) p[k] += f[m][i] * c[i];
ans += k * (p[k] - p[k-1]);
} printf("%.10lf\n", (double)(ans / p[m]));
} return 0;
}
WOJ4694 fortress
有個比較神奇的構造
因爲每個點打一個是一個匹配的過程,我們考慮對每個點拆成5個點或者更多的點使得這一個連通塊選了一個點過後有3個匹配,選了2,3個過後有2個匹配,選了4個過後有1個匹配,5個過後沒有匹配
這樣一來整個圖的最大匹配就是答案
方法如下:
然後就可以用帶花樹做,現學了一波
#include<bits/stdc++.h>
#define N 805
#define M 500050
using namespace std;
int read(){
int cnt = 0, f = 1; char ch = 0;
while(!isdigit(ch)){ ch = getchar(); if(ch == '-')f = -1;}
while(isdigit(ch)){ cnt = cnt*10 + (ch-'0'), ch = getchar();}
return cnt * f;
}
int n, m, T;
int pos(int a, int b){ return n + (a - 1) * m + b;}
int match[N];
int first[N], nxt[M], to[M], tot;
void add(int x, int y){
nxt[++tot] = first[x], first[x] = tot, to[tot] = y;
nxt[++tot] = first[y], first[y] = tot, to[tot] = x;
}
int fa[N]; int find(int x){ return x == fa[x] ? x : fa[x] = find(fa[x]);}
int vis[N], pre[N];
int q[N], hd, tl, node;
int exi[N], TIM;
int lca(int x, int y){
TIM++; for(;;swap(x, y)){
if(x){ x = find(x); if(exi[x] == TIM) return x; else exi[x] = TIM, x = pre[match[x]]; }
}
}
void shrink(int x, int y, int p){
while(find(x) != p){
pre[x] = y; y = match[x];
if(vis[y] == 2) vis[y] = 1, q[++tl] = y;
if(x == find(x)) fa[x] = p;
if(y == find(y)) fa[y] = p;
x = pre[y];
}
}
bool bfs(int s){
for(int i = 1; i <= node; i++) fa[i] = i;
memset(vis, 0, sizeof(vis));
memset(pre, 0, sizeof(pre));
hd = tl = 1; q[1] = s; vis[s] = 1;
while(hd <= tl){
int x = q[hd++];
for(int i = first[x]; i; i = nxt[i]){
int t = to[i];
if(find(t) == find(x) && vis[t] == 2) continue;
if(!vis[t]){
vis[t] = 2; pre[t] = x;
if(!match[t]){
for(int now = t, las; now; now = las){
las = match[pre[now]];
match[now] = pre[now]; match[pre[now]] = now;
} return true;
} vis[match[t]] = 1; q[++tl] = match[t];
}
else{
if(vis[t] == 1){
int l = lca(x, t);
shrink(x, t, l);
shrink(t, x, l);
}
}
}
} return false;
}
int id[8][N];
void Yolanda(){
n = read(), m = read(); node = n;
for(int d = 1; d <= 7; d++) for(int i = 1; i <= m; i++) id[d][i] = ++node;
for(int i = 1; i <= n; i++){
int k = read(); while(k--){
int x = read();
for(int d = 1; d <= 5; d++) add(i, id[d][x]);
}
}
for(int i = 1; i <= m; i++){
for(int d = 1; d <= 5; d++){
add(id[6][i], id[d][i]); add(id[7][i], id[d][i]);
if(d <= 4) add(id[d][i], id[d+1][i]);
else add(id[1][i], id[d][i]);
}
}
int ans = 0;
for(int i = 1; i <= node; i++) if(!match[i] && bfs(i)) ans++;
cout << ans - n << '\n';
}
void FSY(){
memset(match, 0, sizeof(match));
memset(exi, 0, sizeof(exi)); TIM = 0;
memset(first, 0, sizeof(first)); tot = 0;
}
int main(){ T = read(); while(T--) FSY(), Yolanda(); return 0;}
WOJ4695 fibonacci
斐波那契用通項拆開
答案可以由 的復部*2 表示
令 x =
考慮一個修改u對詢問x的影響
兩個分開維護,對於前面那個
維護前面的即可
然後逆元利用
#include<bits/stdc++.h>
#define N 200050
using namespace std;
typedef long long ll;
ll read(){
ll cnt = 0, f = 1; char ch = 0;
while(!isdigit(ch)){ ch = getchar(); if(ch == '-')f = -1;}
while(isdigit(ch)){ cnt = cnt*10 + (ch-'0'), ch = getchar();}
return cnt * f;
}
const int Mod = 1000000007, inv2 = (Mod+1)/2;
ll add(ll a, ll b){ return (a + b) % Mod;}
ll mul(ll a, ll b){ return (a * b) % Mod;}
ll power(ll a, ll b){ ll ans = 1;
for(;b;b>>=1){ if(b&1) ans = mul(ans, a); a = mul(a, a);}
return ans;
}
int n, m, fa[N][20], dep[N], st[N], ed[N], sign;
vector<int> v[N];
struct data{
ll x, y;
data(ll _x = 0, ll _y = 0){ x = _x, y = _y;}
data operator + (const data &a){ return data(add(x, a.x), add(y, a.y));}
data operator - (const data &a){ return data(add(x, Mod-a.x), add(y, Mod-a.y));}
data operator * (const data &a){ return data(add(mul(x, a.x), mul(5, mul(y, a.y))), add(mul(x, a.y), mul(y, a.x)));}
data operator + (const ll &a){ return data(add(x, a), y);}
data operator - (const ll &a){ return data(add(x, Mod-a), y);}
data operator * (const ll &a){ return data(mul(x, a), mul(y, a));}
};
data base = data(inv2, inv2);
data inv(data a){ return data(a.x, Mod-a.y) * power(add(mul(a.x,a.x), Mod-mul(5, mul(a.y,a.y))), Mod-2);}
data ksm(data a, ll b){ data ans(1, 0);
for(;b;b>>=1){ if(b&1) ans = ans*a; a = a*a;}
return ans;
}
void dfs(int u){
st[u] = ++sign;
for(int i = 1; i <= 18; i++) fa[u][i] = fa[fa[u][i-1]][i-1];
for(int i = 0; i < v[u].size(); i++){ int t = v[u][i];
fa[t][0] = u; dep[t] = dep[u] + 1; dfs(t);
} ed[u] = sign;
}
int lca(int x, int y){
if(dep[x] < dep[y]) swap(x, y);
for(int i = 18; i >= 0; i--) if(dep[fa[x][i]] >= dep[y]) x = fa[x][i];
if(x == y) return x;
for(int i = 18; i >= 0; i--) if(fa[x][i] ^ fa[y][i]) x = fa[x][i], y = fa[y][i];
return fa[x][0];
}
struct Segmentree{
data tg[N<<2];
#define mid ((l+r)>>1)
void build(int x, int l, int r){
tg[x] = data(0, 0); if(l == r) return;
build(x<<1, l, mid); build(x<<1|1, mid+1, r);
}
void modify(int x, int l, int r, int L, int R, data k){
if(L<=l && r<=R){ tg[x] = tg[x] + k; return;}
if(L<=mid) modify(x<<1, l, mid, L, R, k);
if(R>mid) modify(x<<1|1, mid+1, r, L, R, k);
}
data query(int x, int l, int r, int p){
if(l == r) return tg[x];
if(p <= mid) return query(x<<1, l, mid, p) + tg[x];
else return query(x<<1|1, mid+1, r, p) + tg[x];
}
#undef mid
}T1, T2;
void upt(int x, ll k){
data v2 = ksm(base, k), v1 = (v2 * base) * inv(ksm(base, dep[x]));
T1.modify(1, 1, n, st[x], ed[x], v1);
T2.modify(1, 1, n, st[x], ed[x], v2);
}
data calc(int x){
if(!x) return data(0, 0);
data ans = T1.query(1, 1, n, st[x]) * ksm(base, dep[x]) - T2.query(1, 1, n, st[x]);
return ans * inv(base-1);
}
ll Qu(int x, int y){
int l = lca(x, y);
data ans = calc(x) + calc(y) - calc(l) - calc(fa[l][0]);
return mul(ans.y, 2);
}
int main(){
n = read(), m = read();
for(int i = 2; i <= n; i++){
int x = read(); v[x].push_back(i);
} dep[1] = 1; dfs(1); T1.build(1, 1, n); T2.build(1, 1, n);
while(m--){
char op[3]; scanf("%s", op);
if(op[0] == 'Q'){ int x = read(), y = read(); cout << Qu(x, y) << '\n';}
if(op[0] == 'U'){ int x = read(); ll k = read(); upt(x, k);}
} return 0;
}