NOIp2018集训test-9-2(pm)

其实这套题我爆0了,T1define 写成ddefine编译错误 T2有两个变量爆int

但是我看zwh不在悄悄地改了,我心里还是十分愧疚(没有)的。主要是林巨已经虐我125了要是再虐我200分我大概这辈子都追不回来了。

1、上学

动态规划入门题

 1 //Achen
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdlib>
 6 #include<vector>
 7 #include<cstdio>
 8 #include<queue>
 9 #include<cmath>
10 #include<set>
11 #include<map>
12 #define Formylove return 0
13 #define For(i,a,b) for(int i=(a);i<=(b);i++)
14 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
15 const int N=2007,p=1000000007;
16 typedef long long LL;
17 typedef double db;
18 using namespace std;
19 int n,f[N][N];
20 
21 template<typename T>void read(T &x)  {
22     char ch=getchar(); x=0; T f=1;
23     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
24     if(ch=='-') f=-1,ch=getchar();
25     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
26 }
27 
28 #define ANS
29 int main() {
30 #ifdef ANS
31     freopen("school.in","r",stdin);
32     freopen("school.out","w",stdout);
33 #endif
34     read(n);
35     f[1][1]=1;
36     For(i,1,n) For(j,i,n) {
37         if(i==1&&j==1) continue;
38         f[i][j]=((LL)f[i][j-1]+f[i-1][j])%p;
39     }
40     printf("%d
",f[n][n]);
41     Formylove;
42 }
View Code

2、旅行

60分树dp入门,100分树dp换根的基本操作。

 1 //Achen
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdlib>
 6 #include<vector>
 7 #include<cstdio>
 8 #include<queue>
 9 #include<cmath>
10 #include<set>
11 #include<map>
12 #define Formylove return 0
13 #define For(i,a,b) for(int i=(a);i<=(b);i++)
14 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
15 const int N=300007;
16 typedef long long LL;
17 typedef double db;
18 using namespace std;
19 int n;
20 
21 template<typename T>void read(T &x)  {
22     char ch=getchar(); x=0; T f=1;
23     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
24     if(ch=='-') f=-1,ch=getchar();
25     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
26 }
27 
28 int ecnt,fir[N],nxt[N<<1],to[N<<1],val[N<<1];
29 void add(int u,int v,int w) {
30     nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v; val[ecnt]=w;
31     nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u; val[ecnt]=w;
32 }
33 
34 #define inf 1e18
35 int sz[N];
36 LL f[N][2],ans[N];
37 void dfs1(int x,int fa) {
38     sz[x]=1;
39     f[x][0]=inf;
40     f[x][1]=-inf;
41     for(int i=fir[x];i;i=nxt[i]) if(to[i]!=fa) {
42         dfs1(to[i],x);
43         sz[x]+=sz[to[i]];
44         f[x][0]=min(f[x][0],f[to[i]][1]+val[i]);
45         f[x][1]=max(f[x][1],f[to[i]][0]+val[i]);
46     }
47     if(sz[x]==1) f[x][0]=f[x][1]=0;
48 }
49 
50 void dfs2(int x,int fa,LL f0,LL f1,LL ef) {
51     LL fi1=-inf,se1=-inf,fi0=inf,se0=inf;
52     if(fa) fi1=f0+ef,fi0=f1+ef;
53     for(int i=fir[x];i;i=nxt[i]) if(to[i]!=fa) {
54         se0=min(se0,f[to[i]][1]+val[i]);
55         if(se0<fi0) swap(fi0,se0);
56         se1=max(se1,f[to[i]][0]+val[i]);
57         if(se1>fi1) swap(fi1,se1);
58     }
59     ans[x]=fi1;
60     for(int i=fir[x];i;i=nxt[i]) if(to[i]!=fa) {
61         LL a,b;
62         if(fi0==f[to[i]][1]+val[i]) a=se0; else a=fi0;
63         if(fi1==f[to[i]][0]+val[i]) b=se1; else b=fi1;
64         if(a==inf&&b==-inf) a=b=0;
65         dfs2(to[i],x,a,b,val[i]);
66     } 
67 }
68 
69 #define ANS 
70 int main() {
71 #ifdef ANS
72     freopen("travel.in","r",stdin);
73     freopen("travel.out","w",stdout);
74 #endif
75     read(n);
76     For(i,2,n) {
77         int u,v,w;
78         read(u); read(v); read(w);
79         add(u,v,w);
80     }
81     dfs1(1,0);
82     dfs2(1,0,0,0,0);
83     For(i,1,n) printf("%lld
",ans[i]);
84     Formylove;
85 }
View Code

3、寻找

两道傻逼题+一道码农题。T3我打了两个小时结果题读错了,式子推错了。。。然后我一开始找环也出了点问题,但是代码改成正解还是比较方便。

容易发现给出的图是一个基环外向树。
先考虑没有环的情况,树上的答案很好算,$p_x$表示从rt开始走,走到x点的概率
$p_{rt}=1$

$p_x=p_{fa[x]}* frac{1}{out_{fa[x]}+1}$

树上x开始走的答案记作$f_x,y$是$x$子树中的点

$f_x=frac{1}{p_x} sum_{y}val_y*p_y$

那么只需要对每棵树按dfs序开棵线段树,维护每个点的 $sum_{y}val_y*p_y$就可以做了

然后考虑环上的点

记从环上的点$x$开始走的答案为$g_x$,设$x$在环上的后继为$y$

$g_x=frac{val_x+g_y}{out[x]+1}+ frac{f_x*out_x}{out_x+1}$

设$t_x= frac{val[x]}{out[x]+1}+frac{f_x*out_x}{out_x+1}$

$k_x=frac{1}{out[x]+1}$

$g_x=t_x+k_x*g_y$

解方程就可以得到(y是环上一点)

$g_x*(1-sum_y frac{1}{out_y+1})=sum_{y,y!=x}从x出发走到y的概率*t_y$

大概这样一个式子,我实在不知道怎么表示了。。

有了这个式子,再对每个环再开一个线段树维护就可以了。

  1 //Achen
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<cstring>
  5 #include<cstdlib>
  6 #include<vector>
  7 #include<cstdio>
  8 #include<queue>
  9 #include<cmath>
 10 #include<set>
 11 #include<map>
 12 #define Formylove return 0
 13 #define For(i,a,b) for(int i=(a);i<=(b);i++)
 14 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
 15 const int N=100007,p=1000000007;
 16 typedef long long LL;
 17 typedef double db;
 18 using namespace std;
 19 int n,m,q,val[N];
 20 char s[N];
 21 
 22 template<typename T>void read(T &x)  {
 23     char ch=getchar(); x=0; T f=1;
 24     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
 25     if(ch=='-') f=-1,ch=getchar();
 26     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
 27 }
 28 
 29 LL mo(LL x) { return x<0?x+p:(x>=p?x-p:x); }
 30 
 31 struct sgtree {
 32     LL sg[N*20];
 33     int rt[N<<1],len[N<<1],ls[N*20],rs[N*20];
 34     int tot;
 35     #define lc ls[x]
 36     #define rc rs[x]
 37     #define mid ((l+r)>>1)
 38     void update(int &x,int l,int r,int pos,int v) {
 39         if(!x) x=++tot;
 40         if(l==r) { sg[x]=v; return; }
 41         if(pos<=mid) update(lc,l,mid,pos,v);
 42         else update(rc,mid+1,r,pos,v);
 43         sg[x]=mo(sg[lc]+sg[rc]);
 44     }
 45     
 46     LL qry(int x,int l,int r,int ql,int qr) {
 47         if(l>=ql&&r<=qr) return sg[x];
 48         if(qr<=mid) return qry(lc,l,mid,ql,qr);
 49         if(ql>mid) return qry(rc,mid+1,r,ql,qr);
 50         return mo(qry(lc,l,mid,ql,qr)+qry(rc,mid+1,r,ql,qr));
 51     }
 52 }t;
 53 
 54 LL ksm(LL a,LL b) {
 55     LL rs=1,bs=a;
 56     while(b) {
 57         if(b&1) rs=rs*bs%p;
 58         bs=bs*bs%p;
 59         b>>=1;
 60     }
 61     return rs;
 62 }
 63 
 64 LL k1[N],k2[N];
 65 LL frc(LL a,LL b) { return a*ksm(b,p-2)%p; }
 66 
 67 int ecnt,fir[N],nxt[N],to[N],in[N],out[N];
 68 void add(int u,int v) {
 69     nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v; out[u]++; in[v]++;
 70 }
 71 
 72 int get(int x,int y) { return (x-1)*m+y; }
 73 
 74 int vis[N],tag[N],pi[N],nx[N];
 75 int dfs(int x,int st) {
 76     if(vis[x]==st) return x;
 77     if(vis[x]) return 0;
 78     vis[x]=st;
 79     int rs=0;
 80     for(int i=fir[x];i;i=nxt[i]) {
 81         int tp=dfs(to[i],st);
 82         if(tp) { rs=tp; nx[x]=to[i]; }
 83     }    
 84     tag[x]=rs;
 85     return rs;
 86 }
 87 
 88 int id[N],ed[N];
 89 void dfs_H(int x) {
 90     int rt=x,hc=0;
 91     id[x]=1; pi[x]=1;
 92     for(;;) {
 93         if(nx[x]!=rt) pi[nx[x]]=(LL)pi[x]*k1[x]%p;
 94         x=nx[x];
 95         hc++;
 96         if(x==rt) break;
 97         ed[rt]=x;
 98         id[x]=hc+1;
 99     }
100     t.len[n*m+rt]=hc;
101 }
102 
103 int sum[N],top[N],fa[N],dfn[N],dfk,sz[N];
104 void dfs2(int x,LL P,int Top) {
105     sz[x]=1;
106     top[x]=Top;
107     dfn[x]=++dfk;
108     if(!tag[x]) pi[x]=P;
109     for(int i=fir[x];i;i=nxt[i]) if(!tag[to[i]]) {
110         fa[to[i]]=x;
111         if(x==Top&&tag[x]) dfs2(to[i],P*frc(1,out[x])%p,Top); 
112         else dfs2(to[i],P*k1[x]%p,Top);
113         sz[x]+=sz[to[i]];
114     }
115 }
116 
117 #define ANS
118 int main() {
119 #ifdef ANS
120     freopen("search.in","r",stdin);
121     freopen("search.out","w",stdout);
122 #endif
123     read(n); read(m); 
124     t.tot=0;
125     For(i,1,n) {
126         scanf("%s",s+1);
127         For(j,1,m) {
128             if(s[j]=='U') add(get(i-1,j),get(i,j));
129             if(s[j]=='D') add(get(i+1,j),get(i,j));
130             if(s[j]=='L') add(get(i,j-1),get(i,j));
131             if(s[j]=='R') add(get(i,j+1),get(i,j));
132         }
133     }
134     For(i,1,n*m) {
135         k1[i]=ksm(out[i]+1,p-2);
136         k2[i]=(1-k1[i]+p)%p;
137     }
138     For(i,1,n*m) if(!vis[i]) dfs(i,i); 
139     For(i,1,n*m) if(tag[i]&&!id[i]) dfs_H(tag[i]);
140     For(i,1,n*m) if(!in[i]||tag[i]) {
141         dfk=0;
142         dfs2(i,1,i);
143         t.len[i]=dfk;
144     }
145     read(q);
146     For(i,1,q) {
147         int o,x,y,z;
148         read(o); read(x); read(y);
149         x=get(x,y);
150         if(o==1) {
151             read(z); val[x]=z;
152             LL upv=tag[x]?z:(LL)z*pi[x]%p;
153             t.update(t.rt[top[x]],1,t.len[top[x]],dfn[x],upv);
154             if(tag[top[x]]) {
155                 int ii=top[x];
156                 int rt=tag[ii];
157                 LL f=t.sg[t.rt[ii]];
158                 LL tt=((LL)val[ii]*k1[ii]%p+f*k2[ii]%p)%p;
159                 tt=tt*pi[ii]%p;
160                  t.update(t.rt[rt+n*m],1,t.len[rt+n*m],id[top[x]],tt); 
161             }
162         }
163         else {
164             if(!tag[x]) {
165                 LL ans=t.qry(t.rt[top[x]],1,t.len[top[x]],dfn[x],dfn[x]+sz[x]-1);
166                 ans=ans*frc(1,pi[x])%p;
167                 printf("%lld
",ans);
168             }
169             else {
170                 int rt=n*m+tag[x],edd=ed[tag[x]];
171                 LL ans1=t.qry(t.rt[rt],1,t.len[rt],id[x],t.len[rt]);
172                 ans1=ans1*frc(1,pi[x])%p;
173                 LL ans2=id[x]>1?t.qry(t.rt[rt],1,t.len[rt],1,id[x]-1):0;
174                 if(ans2) ans2=ans2*frc(pi[edd],pi[x])%p*k1[edd]%p;
175                 LL ans=frc((ans1+ans2)%p,(1-(LL)pi[edd]*k1[edd]%p+p)%p);
176                 printf("%lld
",ans); 
177             }
178         }
179     }
180     Formylove;
181 }
View Code

 

原文地址:https://www.cnblogs.com/Achenchen/p/9577729.html