题解:P8290 [省选联考 2022] 填树
[省选联考 2022] 填树
如果不知道拉格朗日插值,其实很难有勇气做下去。因此,本篇题解认为读者已经熟悉拉格朗日插值,并从此角度去考虑问题。
首先,想着复杂度关于
接着会想到枚举一下最小值,就知道了最大值,范围确定下来,是容易
做了以上的工作,复杂度就是
Code
#include <iostream>
#include <algorithm>
#include <string.h>
#include <iomanip>
#include <bitset>
#include <math.h>
#include <string>
#include <vector>
#include <queue>
#include <set>
#include <map>
#define fst first
#define scd second
#define db double
#define ll long long
#define mp make_pair
#define pb push_back
#define eb emplace_back
#define vi vector <int>
#define pii pair <int, int>
#define sz(x) ((int)x.size())
#define ms(f, x) memset(f, x, sizeof(f))
#define L(i, j, k) for (int i=(j); i<=(k); ++i)
#define R(i, j, k) for (int i=(j); i>=(k); --i)
#define ACN(i, H_u) for (int i=H_u; i; i=E[i].nxt)
using namespace std;
template <typename INT> void rd(INT &res) {
res=0; bool f=false; char ch=getchar();
while (ch<'0'||ch>'9') f|=ch=='-', ch=getchar();
while (ch>='0'&&ch<='9') res=(res<<1)+(res<<3)+(ch^48), ch=getchar();
res=(f?-res:res);
}
template <typename INT, typename...Args>
void rd(INT &x, Args &...y) { rd(x), rd(y...); }
//dfs
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const int maxn=200;
const int N=maxn+10;
int H[N], edge_cnt, n, m, kn, sum[N], cnt[N], lb, rb, fac[N], inv[N], pre[N], suf[N], d[N<<2], t1[N], t2[N], res1, res2;
//wmr
int moda(int x) { return x>=mod?x-mod:x; }
int mods(int x) { return x<0?x+mod:x; }
struct Edge { int nxt, to; } E[N<<1];
void add(int u, int v) { E[++edge_cnt]={H[u], v}; H[u]=edge_cnt; }
struct node { int l, r; } a[N];
int quick_power(int x, int y) {
int res=1;
while (y) {
if (y&1) res=(ll)res*x%mod;
x=(ll)x*x%mod, y>>=1;
}
return res;
}
//incra
void dfs(int u, int pre) {
int r=min(rb, a[u].r), l=max(lb, a[u].l);
if (l>r) l=1, r=0;
int c0=r-l+1, s0=((ll)(l+r)*(r-l+1)>>1)%mod;
cnt[u]=c0, sum[u]=s0; res1=moda(res1+c0), res2=moda(res2+s0);
ACN(i, H[u]) {
int v=E[i].to;
if (v==pre) continue;
dfs(v, u);
res1=(res1+(ll)cnt[u]*cnt[v])%mod, res2=(res2+(ll)cnt[u]*sum[v]+(ll)cnt[v]*sum[u])%mod;
cnt[u]=(cnt[u]+(ll)c0*cnt[v])%mod, sum[u]=(sum[u]+(ll)cnt[v]*s0+(ll)c0*sum[v])%mod;
}
}
int lag(int a[], int m) {
int ans=0;
pre[0]=1; L(i, 1, n+2) pre[i]=(ll)pre[i-1]*(m-i)%mod;
suf[n+3]=1; R(i, n+2, 1) suf[i]=(ll)suf[i+1]*(m-i)%mod;
L(i, 1, n+2) ans=((ll)a[i]*pre[i-1]%mod*suf[i+1]%mod*inv[i-1]%mod*inv[n+2-i]%mod*(((n+2-i)&1)?mod-1:1)+ans)%mod;
return ans;
}
//lottle
signed main() {
// ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
// freopen(".in", "r", stdin);
// freopen(".out", "w", stdout);
fac[0]=1; L(i, 1, maxn+2) fac[i]=(ll)fac[i-1]*i%mod;
inv[maxn+2]=quick_power(fac[maxn+2], mod-2); R(i, maxn+1, 0) inv[i]=(ll)inv[i+1]*(i+1)%mod;
rd(n, kn);
L(i, 1, n) {
rd(a[i].l, a[i].r);
d[i*4-3]=a[i].l, d[i*4-2]=max(a[i].l-kn, 0);
d[i*4-1]=a[i].r, d[i*4]=max(a[i].r-kn, 0);
d[n*4+1]=max(d[n*4+1], a[i].r+1);
}
sort(d+1, d+n*4+2); m=unique(d+1, d+n*4+2)-d-1;
L(i, 1, n-1) { int u, v; rd(u, v); add(u, v), add(v, u); }
int ans1=0, ans2=0;
L(i, 1, m-1) {
int rc=d[i+1]-d[i], cnt=min(n+2, rc);
L(j, 1, cnt) {
lb=d[i]+j, rb=d[i]+j+kn-1; res1=res2=0;
dfs(1, 0);
res1=mods(-res1), res2=mods(-res2);
--lb; dfs(1, 0);
ans1=moda(ans1+res1), ans2=moda(ans2+res2);
t1[j]=ans1, t2[j]=ans2;
}
if (rc<=n+2) continue;
ans1=lag(t1, rc), ans2=lag(t2, rc);
}
printf("%d\n%d\n", ans1, ans2);
return 0;
}