今天心态爆炸
一直在练的树dp没做出来
以为自己没问题比较擅长的容斥也没做出来
最后其实T2自己的做法再想一想就是正解
算了说出来也没人信
T1如果沿用之前的思路应该也能想出来...
考试的时候不会再崩溃了
因为没资格
做题的顺序改一下吧 看啥做啥 觉得自己能做就想到底
不要以为自己能快速切某个题
如果真能快速想出来任何做法就写了
暴力以后对拍也能用上
这样想题才能专心
T1 matrix 20/100
没练容斥....
容斥就是多退少补
想了O(n^2)却没写
就是
(其实还是指+1以为是+i*j)
问题就在于如何化简
题解是先把n-i,n-j变成i,j
然后把j压到一起
把 -3i视为一项 然后...
这不就是个二项式定理吗
所以愉快解决
注意上面只能处理 i*j不为0的情况
为0暴力手算即可
Code:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #include<queue> 6 #include<iostream> 7 #define ms(a,b) memset(a,b,sizeof a) 8 #define rep(i,a,n) for(int i = a;i <= n;i++) 9 #define per(i,n,a) for(int i = n;i >= a;i--) 10 #define inf 2147483647 11 using namespace std; 12 typedef long long ll; 13 typedef double D; 14 #define eps 1e-8 15 ll read() { 16 ll as = 0,fu = 1; 17 char c = getchar(); 18 while(c < '0' || c > '9') { 19 if(c == '-') fu = -1; 20 c = getchar(); 21 } 22 while(c >= '0' && c <= '9') { 23 as = as * 10 + c - '0'; 24 c = getchar(); 25 } 26 return as * fu; 27 } 28 //head 29 const int N = 1000006; 30 const ll mod = 998244353; 31 int n; 32 ll fac[N],inv[N]; 33 ll ksm(ll a,ll b) { 34 ll tmp = 1; 35 while(b) { 36 if(b & 1) tmp = tmp * a % mod; 37 a = a * a % mod; 38 b >>= 1; 39 } 40 return tmp; 41 } 42 43 void initfac(int n) { 44 fac[0] = fac[1] = inv[1] = inv[0] = 1; 45 rep(i,2,n) fac[i] = fac[i-1] * i % mod; 46 inv[n] = ksm(fac[n],mod - 2); 47 per(i,n-1,2) inv[i] = inv[i+1] * (i+1) % mod; 48 } 49 50 ll C(ll n,ll m) {return fac[n] * inv[m] % mod * inv[n-m] % mod;} 51 52 ll ans = 0; 53 ll sgn(ll x) {return (x & 1) ? 1 : mod - 1;} 54 int main() { 55 n = read(); 56 initfac(n); 57 rep(i,1,n) ans = (ans + ksm(3,i) * ksm(3,n*(n-i)) % mod * 2 * sgn(i) % mod * C(n,i) % mod) % mod; 58 rep(i,0,n-1) { 59 ll tmp = 3ll * sgn(i) * C(n,i) % mod; 60 ll tmpp = (mod - ksm(3,i)) % mod; 61 tmpp = (ksm(tmpp + 1,n) - ksm(tmpp,n) + mod) % mod; 62 tmp = tmp * tmpp % mod; 63 ans = (ans + tmp) % mod; 64 } 65 printf("%lld ",ans); 66 return 0; 67 }
T2 Tree 0/100
树dp水题
并没有做出来
准确的说是做出来了并没有写
最后完全心态爆炸 如果敲一下怎么也有写跪那一帮人的30吧
先尽量减 判断是否合法
然后 重新 模拟减的过程
至于如何分配各个儿子减的值
选择在处理父亲的时候减掉儿子的边权
Code:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #include<queue> 6 #include<iostream> 7 #define ms(a,b) memset(a,b,sizeof a) 8 #define rep(i,a,n) for(int i = a;i <= n;i++) 9 #define per(i,n,a) for(int i = n;i >= a;i--) 10 #define inf 2147483647 11 using namespace std; 12 typedef long long ll; 13 typedef double D; 14 #define eps 1e-8 15 ll read() { 16 ll as = 0,fu = 1; 17 char c = getchar(); 18 while(c < '0' || c > '9') { 19 if(c == '-') fu = -1; 20 c = getchar(); 21 } 22 while(c >= '0' && c <= '9') { 23 as = as * 10 + c - '0'; 24 c = getchar(); 25 } 26 return as * fu; 27 } 28 //head 29 const int N = 200006; 30 int n; 31 int head[N],nxt[N<<1],mo[N<<1],cnt; 32 ll cst[N<<1],maxx[N<<1]; 33 void _add(int x,int y,ll A,ll B) { 34 mo[++cnt] = y; 35 nxt[cnt] = head[x]; 36 head[x] = cnt; 37 cst[cnt] = A,maxx[cnt] = B; 38 } 39 void add(int x,int y) { 40 ll A = read(),B = read(); 41 // printf("%d %d %d %d ",x,y,A,B); 42 _add(x,y,A,B),_add(y,x,A,B); 43 } 44 45 ll w[N],f[N]; 46 void dfs(int x,int p) { 47 for(int i = head[x];i;i = nxt[i]) { 48 int sn = mo[i]; 49 if(sn == p) continue; 50 dfs(sn,x); 51 ll a = cst[i],b = maxx[i]; 52 w[x] += w[sn] + a; 53 f[x] += f[sn] + a; 54 ll C = min(a - 1,b - f[sn]); 55 if(C < 0) puts("-1"),exit(0); 56 f[x] -= C; 57 } 58 } 59 ll dp[N],sum[N]; 60 void Dp(int x,int p) { 61 sum[x] = 0; 62 for(int i = head[x];i;i = nxt[i]) { 63 int sn = mo[i]; 64 if(sn == p) continue; 65 Dp(sn,x); 66 ll a = cst[i],b = maxx[i]; 67 if(b >= sum[sn]) { 68 dp[x] += dp[sn],sum[x] += sum[sn] + a; 69 } else { 70 dp[x] += dp[sn] + sum[sn] - b; 71 sum[sn] = b,sum[x] += a + b; 72 } 73 } 74 } 75 76 int main() { 77 freopen("tree.in","r",stdin); 78 freopen("tree.out","w",stdout); 79 n = read(); 80 rep(i,2,n) add(read(),read()); 81 dfs(1,1),Dp(1,1); 82 printf("%lld ",dp[1]); 83 return 0; 84 }
T3 count 10/100
dp 完全想不到维护多少条相交路径啊....
dp[i][j]表示i深度子树有j条不想交路径的方案数
所以可以根据路径是否经过根节点分类计数
Code:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #include<queue> 6 #include<iostream> 7 #define ms(a,b) memset(a,b,sizeof a) 8 #define rep(i,a,n) for(int i = a;i <= n;i++) 9 #define per(i,n,a) for(int i = n;i >= a;i--) 10 #define inf 2147483647 11 using namespace std; 12 typedef long long ll; 13 typedef double D; 14 #define eps 1e-8 15 ll read() { 16 ll as = 0,fu = 1; 17 char c = getchar(); 18 while(c < '0' || c > '9') { 19 if(c == '-') fu = -1; 20 c = getchar(); 21 } 22 while(c >= '0' && c <= '9') { 23 as = as * 10 + c - '0'; 24 c = getchar(); 25 } 26 return as * fu; 27 } 28 //head 29 const int N = 405; 30 const int mod = 1e9+7; 31 int n; 32 ll fac[N],inv[N]; 33 ll ksm(ll a,ll b) { 34 ll tmp = 1; 35 while(b) { 36 if(b & 1) tmp = tmp * a % mod; 37 a = a * a % mod; 38 b >>= 1; 39 } 40 return tmp; 41 } 42 43 void initfac(int n) { 44 fac[0] = fac[1] = inv[1] = inv[0] = 1; 45 rep(i,2,n) fac[i] = fac[i-1] * i % mod; 46 inv[n] = ksm(fac[n],mod - 2); 47 per(i,n-1,2) inv[i] = inv[i+1] * (i+1) % mod; 48 } 49 50 ll C(ll n,ll m) {return fac[n] * inv[m] % mod * inv[n-m] % mod;} 51 52 ll dp[N][N]; 53 int main() { 54 freopen("count.in","r",stdin); 55 freopen("count.out","w",stdout); 56 n = read(); 57 initfac(n); 58 dp[1][0] = dp[1][1] = 1; 59 rep(i,2,n) { 60 rep(j,0,n) rep(k,0,n-j) { 61 dp[i][j+k] = (dp[i][j+k] + dp[i-1][j] * dp[i-1][k] % mod) % mod; 62 dp[i][j+k+1] = (dp[i][j+k+1] + dp[i-1][j] * dp[i-1][k] % mod) % mod; 63 dp[i][j+k] = (dp[i][j+k] + (j+k<<1) * dp[i-1][j] % mod * dp[i-1][k] % mod) % mod; 64 if(j+k) dp[i][j+k-1] = (dp[i][j+k-1] + (C(j+k,2)<<1) * dp[i-1][j] % mod * dp[i-1][k] % mod) % mod; 65 } 66 } 67 printf("%lld ",dp[n][1]); 68 return 0; 69 }