NOI2013完整题解

Day 1

T1:向量内积

T2:树的计数

T3:小Q的修炼

Day 2

T1:矩阵游戏

最简单的一道题。首先已知f[i][1]可以通过等比数列求和公式轻松推出f[i][m]。然后合并系数可以轻松从f[1][1]得到f[n][1],最后直接从f[n][1]推到f[n][m]即可。注意公比为1要特殊处理。

关于读入,由于n和m在公比不为1时是指数,为1时是系数,所以要边读边mod p或p-1。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 5 using namespace std;
 6 
 7 const int mod=1000000007;
 8 int n,m,a,b,c,d,n1,m1,X,Y;
 9 char s[1000010];
10 
11 void Rd(int &n,int &n1){
12     scanf("%s",s+1); int l=strlen(s+1); n=0; n1=0;
13     rep(i,1,l) n=(n*10ll+s[i]-'0')%(mod-1),n1=(n1*10ll+s[i]-'0')%mod;
14 }
15 
16 int ksm(int a,int b){
17     int res=1;
18     for (; b; a=1ll*a*a%mod,b>>=1)
19         if (b&1) res=1ll*res*a%mod;
20     return res;
21 }
22 
23 void cal1(int a,int b,int n){ if (n<0) n+=mod; X=1; Y=1ll*n*b%mod; }
24 void cal(int a,int b,int n){ if (n<0) n+=mod-1; X=ksm(a,n); Y=1ll*(X-1)*ksm(a-1,mod-2)%mod*b%mod; }
25 
26 int main(){
27     freopen("matrix.in","r",stdin);
28     freopen("matrix.out","w",stdout);
29     Rd(n,n1); Rd(m,m1); scanf("%d%d%d%d",&a,&b,&c,&d);
30     if (a==1) cal1(a,b,m1-1); else cal(a,b,m-1);
31     int p=X,q=Y,w=(p+q)%mod,u=1ll*c*p%mod,v=(1ll*c*q+d)%mod;
32     if (u==1) cal1(u,v,n1-1); else cal(u,v,n-1);
33     w=(1ll*X+Y)%mod; w=(1ll*p*w+q)%mod; printf("%d\n",w);
34     return 0;
35 }
View Code

T2:书法家

T3:快餐店

首先如果是树,答案显然为直径的一半,这启发我们不要太深入的考虑环套树DP,而是使用常规的破环成树的方法。

显然所有点对间的最短路径可以都不经过某条边,枚举这条不需要的边,破环成树,在树上做前缀和与前缀最大值,再搞一搞就好了。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 4 #define For(i,x) for (int i=h[x],k; i; i=nxt[i])
 5 typedef long long ll;
 6 using namespace std;
 7 
 8 const int N=100010;
 9 int n,cnt,tot,tim,u,v,w,dfn[N],fa[N],a[N],b[N],c[N],h[N],to[N<<1],nxt[N<<1],val[N<<1];
10 ll f[N],u1[N],u2[N],v1[N],v2[N],ans;
11 bool d[N];
12 
13 void add(int u,int v,int w){ to[++cnt]=v; nxt[cnt]=h[u]; val[cnt]=w; h[u]=cnt; }
14 
15 void dfs(int x){
16     dfn[x]=++tim;
17     For(i,x) if ((k=to[i])!=fa[x]){
18         if (!dfn[k]){ fa[k]=x; c[k]=val[i]; dfs(k); }
19         else if (dfn[k]>dfn[x]){
20             for (; k!=x; k=fa[k]) d[k]=1,a[++tot]=k,b[tot]=c[k];
21             d[x]=1; a[++tot]=x; b[tot]=val[i];
22         }
23     }
24 }
25 
26 void DP(int x,int fa){
27     For(i,x) if ((k=to[i])!=fa && !d[k])
28         DP(k,x),ans=max(ans,f[x]+f[k]+val[i]),f[x]=max(f[x],f[k]+val[i]);
29 }
30 
31 int main(){
32     freopen("food.in","r",stdin);
33     freopen("food.out","w",stdout);
34     scanf("%d",&n);
35     rep(i,1,n) scanf("%d%d%d",&u,&v,&w),add(u,v,w),add(v,u,w);
36     dfs(1); ll sm=0,mx=0;
37     rep(i,1,tot) DP(a[i],0);
38     rep(i,1,tot){
39         sm+=b[i-1]; u1[i]=max(u1[i-1],f[a[i]]+sm);
40         v1[i]=max(v1[i-1],f[a[i]]+sm+mx);
41         mx=max(mx,f[a[i]]-sm);
42     }
43     ll tmp=b[tot]; sm=mx=b[tot]=0;
44     for (int i=tot; i; i--){
45         sm+=b[i]; u2[i]=max(u2[i+1],f[a[i]]+sm);
46         v2[i]=max(v2[i+1],f[a[i]]+sm+mx);
47         mx=max(mx,f[a[i]]-sm);
48     }
49     ll mn=v1[tot];
50     rep(i,1,tot-1) mn=min(mn,max(max(v1[i],v2[i+1]),u1[i]+u2[i+1]+tmp));
51     ans=max(ans,mn); printf("%lld.%d\n",ans>>1,(ans&1)?5:0);
52     return 0;
53 }
View Code

猜你喜欢

转载自www.cnblogs.com/HocRiser/p/9276394.html
今日推荐