luogu P4516 [JSOI2018]潛入行動
阿新 • • 發佈:2020-07-13
LINK:潛入行動
初看題感覺很不可做 但是樹形dp的狀態過於明顯。
容易設\(f_{x,j,l,r}\)表示x為根子樹內放了j個裝置且子樹內都被覆蓋l表示x是否被覆蓋r表示x是否放裝置的方案數。
初值我是上面四個狀態都設為1 轉移分類討論一下也不困難。
然後需要容斥一下。
複雜度看起來是\(n\cdot k^2\)的 其實是\(n\cdot k\)的 證明 這個我就不口胡了。
當然還有一種轉移是隻給正確的狀態轉移 這樣就不需要容斥了 可能常數會小一點。
我常數比較大 開o2才能過 列舉的邊界注意把握好 這是TLE和AC的區別。
code
//#include<bits\stdc++.h> #include<iostream> #include<iomanip> #include<cstdio> #include<cstring> #include<string> #include<ctime> #include<cmath> #include<cctype> #include<cstdlib> #include<queue> #include<deque> #include<stack> #include<vector> #include<algorithm> #include<utility> #include<bitset> #include<set> #include<map> #define ll long long #define db double #define INF 10000000000000000ll #define ldb long double #define pb push_back #define put_(x) printf("%d ",x); #define get(x) x=read() #define gt(x) scanf("%d",&x) #define gi(x) scanf("%lf",&x) #define put(x) printf("%d\n",x) #define putl(x) printf("%lld\n",x) #define gc(a) scanf("%s",a+1) #define rep(p,n,i) for(RE int i=p;i<=n;++i) #define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]]) #define fep(n,p,i) for(RE int i=n;i>=p;--i) #define vep(p,n,i) for(RE int i=p;i<n;++i) #define pii pair<int,int> #define mk make_pair #define RE register #define P 1000000007 #define gf(x) scanf("%lf",&x) #define pf(x) ((x)*(x)) #define uint unsigned long long #define ui unsigned #define EPS 1e-4 #define sq sqrt #define S second #define F first #define mod 1000000007 using namespace std; char buf[1<<15],*fs,*ft; inline char getc() { return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++; } inline int read() { RE int x=0,f=1;RE char ch=getc(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();} return x*f; } const int MAXN=100002,maxn=102; int n,len,lim,cc,ww; int f[MAXN][maxn][2][2],sz[MAXN],g[maxn][2][2]; int lin[MAXN],nex[MAXN<<1],ver[MAXN<<1]; inline int mul(int x,int y){return (ll)x*y%mod;} inline int add2(int x,int y){return x+y>=mod?x+y-mod:x+y;} inline void add(int &x,int y){x=x+y>=mod?x+y-mod:x+y;} inline int mus(int x,int y){return x-y<0?x-y+mod:x-y;} inline void add1(int x,int y) { ver[++len]=y;nex[len]=lin[x];lin[x]=len; ver[++len]=x;nex[len]=lin[y];lin[y]=len; } inline void dfs(int x,int fa) { f[x][0][0][0]=f[x][1][0][1]=1;sz[x]=1; f[x][1][1][1]=f[x][0][1][0]=1; go(x)if(tn!=fa) { dfs(tn,x); rep(0,min(sz[x],lim),j)rep(0,1,l)rep(0,1,r)g[j][l][r]=f[x][j][l][r],f[x][j][l][r]=0; cc=min(sz[x],lim); rep(0,cc,j) { rep(0,sz[tn],k) { if(j+k<=lim) { add(f[x][j+k][0][0],mul(f[tn][k][1][0],g[j][0][0])); add(f[x][j+k][0][1],mul(add2(f[tn][k][0][0],f[tn][k][1][0]),g[j][0][1])); add(f[x][j+k][1][0],mul(add2(f[tn][k][1][1],f[tn][k][1][0]),g[j][1][0])); add(f[x][j+k][1][1],mul(add2(f[tn][k][1][0],f[tn][k][1][1]),g[j][1][1])); add(f[x][j+k][1][1],mul(add2(f[tn][k][0][1],f[tn][k][0][0]),g[j][1][1])); } else break; } } sz[x]+=sz[tn]; } cc=min(sz[x],lim); rep(0,cc,j)f[x][j][1][0]=mus(f[x][j][1][0],f[x][j][0][0]),f[x][j][1][1]=mus(f[x][j][1][1],f[x][j][0][1]); } int main() { //freopen("1.in","r",stdin); get(n);get(lim); rep(2,n,i)add1(read(),read()); dfs(1,0);put(add2(f[1][lim][1][0],f[1][lim][1][1])); return 0; }