爆算碾标程实例
不太会多项式……不太会线段树合并
那就只能O(n^2*w^2)爆算+乱搞优化(见代码)
(这里网上都说是O(n*w^2),我不太明白,也许是我算的不对,望有识之士教我)
愣是卡进luogu最优解第3页
自以为要卡常数,结果卡了好久以后发现是死循环……
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=2005; const int modd=64123; unsigned short int n, k, w; unsigned short int dp[maxn][maxn], p[maxn]; unsigned short int can[maxn], f[maxn]; struct gra { unsigned short int tm, st[maxn*2], nx[maxn*2], to[maxn*2], tt[maxn*2]; inline void adde(unsigned short int a, unsigned short int b) { tm++; nx[tm]=st[a]; st[a]=tm; to[tm]=b; } void dfs(unsigned short int x, unsigned short int fa) { //cout<<x<<‘ ‘<<fa<<endl; if(fa == f[x]) return; else f[x]=fa; unsigned short int i, y, j, q, ttt; memset(dp[x], 0, sizeof(dp[x])); dp[x][p[x]]=1; can[x]=p[x]; for(i=st[x]; i != 0; i=nx[i]) { y=to[i]; if(y == fa) continue; dfs(y, x); ttt=can[x]; for(j=0; j <= can[y]; ++j) { for(q=0; q <= ttt; ++q) { if(q+j > k) break; tt[q+j]=((int)tt[q+j]+(int)dp[x][q]*(int)dp[y][j]%modd)%modd; can[x]<q+j?can[x]=q+j:can[x]; } } for(j=0; j <= can[x]; ++j) { dp[x][j]=((int)dp[x][j]+(int)tt[j])%modd; tt[j]=0; } } /* cout<<x<<endl; for(i=0; i <= k; i++) { cout<<dp[x][i]<<‘ ‘; }cout<<endl; */ return; } } G; struct dd { unsigned short int num; unsigned short int pl; }d[maxn]; bool cmp(dd a, dd b) { return a.num > b.num; } int main() { //freopen("data5.in", "r", stdin); unsigned short int i, ta, j, tb, ans; scanf("%hu%hu%hu", &n, &k, &w); for(i=1; i <= n; ++i) { scanf("%hu", &d[i].num); d[i].pl=i; } sort(d+1, d+1+n, cmp); for(i=1; i <= n-1; ++i) { scanf("%hu%hu", &ta, &tb); G.adde(ta, tb); G.adde(tb, ta); } ans=0; for(i=1; i <= n; ++i) { p[d[i].pl]=1; //cout<<i<<endl; if(i < k) continue; G.dfs(d[i].pl, d[i].pl); ans=((int)ans+(int)d[i].num*(int)dp[d[i].pl][k]%modd)%modd; //cout<<i<<endl; } printf("%hu\n", ans); return 0; }
原文地址:https://www.cnblogs.com/crraphael/p/11488402.html
时间: 2024-09-30 15:29:03