181106 solution

今天心态爆炸

一直在练的树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\n",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\n",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\n",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\n",dp[n][1]);
68     return 0;
69 }

 

posted @ 2018-11-06 20:39  白怀潇  阅读(145)  评论(0编辑  收藏  举报