题解#2

上一篇好像已经够长了。。。新开一篇

现在做了几道:

                                                                    12

BZOJ3829: [Poi2014]FarmCraft

考虑树DP,我们发现子树走的顺序不同最优值也不同。所以需要安排一个顺序,使得该子树中最晚安装好的点最早安装好。
这就需要国王游戏中考虑相邻节点的类似方法,具体推导可以见claris神犇的题解:

http://hi.baidu.com/clrs97/item/408d0adb61dc4f5d21e25078

 1 int n,head[maxn],tot,f[maxn],d[maxn],a[maxn];
 2 struct edge{int go,next;}e[2*maxn];
 3 inline void add(int x,int y)
 4 {
 5     e[++tot]=(edge){y,head[x]};head[x]=tot;
 6     e[++tot]=(edge){x,head[y]};head[y]=tot;
 7 }
 8 inline bool cmp(int x,int y){return max(f[x],d[x]+2+f[y])<max(f[y],d[y]+2+f[x]);}
 9 inline void dfs(int x,int fa)
10 {
11     for4(i,x)if(y!=fa)dfs(y,x),d[x]+=d[y]+2; 
12     int m=0,sum=0;
13     for4(i,x)if(y!=fa)a[++m]=y;
14     sort(a+1,a+m+1,cmp);
15     for1(i,m)
16     {
17         f[x]=max(f[x],sum+f[a[i]]+1);
18         sum+=d[a[i]]+2;
19     }
20 }
21 
22 int main()
23 
24 {
25 
26     freopen("input.txt","r",stdin);
27 
28     freopen("output.txt","w",stdout);
29 
30     n=read();
31     for1(i,n)f[i]=read();
32     int ans=f[1];
33     for1(i,n-1)add(read(),read());
34     dfs(1,0);
35     ans=max(2*n-2+ans,f[1]);
36     printf("%d\n",ans);
37 
38     return 0;
39 
40 }  
View Code

 

BZOJ2219: 数论之神

AC了此题有种满满的成就感233

题解戳这里吧:http://www.cnblogs.com/dyllove98/archive/2013/08/05/3239030.html

or  http://hi.baidu.com/lydrainbowcat/item/de72f307d9a4b7823c42e281

我越来越懒了

 1 int pr[maxn];
 2 map<int,int>mp;
 3 inline int gcd(int x,int y){return y?gcd(y,x%y):x;}
 4 inline int power(int x,int y,int p)
 5 {
 6     int t=1;
 7     for(;y;y>>=1,x=(ll)x*x%p)
 8         if(y&1)t=(ll)t*x%p;
 9     return t;
10 }
11 inline int gen(int p)
12 {
13     int t=p-1,m=0;
14     for(int i=2;i*i<=t;i++)if(t%i==0)
15     {
16         pr[++m]=i;
17         while(t%i==0)t/=i;
18     }
19     if(t>1)pr[++m]=t;
20     for(int i=2;;i++)
21     {
22         bool flag=0;
23         for1(j,m)if(power(i,(p-1)/pr[j],p)==1){flag=1;break;}
24         if(!flag)return i;
25     }
26 }
27 inline int bsgs(int a,int b,int p)
28 {
29     if(!b)return 0;
30     int m=ceil(sqrt(p));
31     mp.clear();
32     for(int i=0,j=1;i<m;i++,j=(ll)j*a%p)mp[(ll)b*j%p]=i;
33     a=power(a,m,p);
34     for(int i=1,j=a;i<=m;i++,j=(ll)j*a%p)
35         if(mp.find(j)!=mp.end())return i*m-mp[j];
36     return -1;
37 }    
38 inline int solve(int a,int b,int p,int c,int pc)
39 {
40     b%=pc;
41     if(gcd(b,pc)>1)
42     {
43         if(b)
44         {
45             int t=0;
46             while(b%p==0)b/=p,pc/=p,t++,c--;
47             if(t%a)return 0;
48                 }else return power(p,c-c/a-(int)(c%a>0),inf);//不可写成c-ceil(c/a)!!! 
49     }
50     b=bsgs(gen(p),b,pc);
51     pc-=pc/p;
52     a=gcd(a,pc);
53     return b%a?0:a;
54 }
55 
56 int main()
57 
58 {
59 
60     freopen("input.txt","r",stdin);
61 
62     freopen("output.txt","w",stdout);
63 
64     int T=read();
65     while(T--)
66     {
67         int a=read(),b=read(),p=2*read()+1,ans=1;
68         for(int i=2;i*i<=p&&ans;i++)if(p%i==0)
69         {
70             int j=0,k=1;
71             while(p%i==0)p/=i,k*=i,j++;
72             ans*=solve(a,b,i,j,k);
73         }
74         if(ans&&p>1)ans*=solve(a,b,p,1,p);
75         printf("%d\n",ans);
76     }
77 
78     return 0;
79 
80 }  
View Code

 

BZOJ3157: 国王奇遇记

3种做法:

1)构造矩阵快速幂m^3logn

2)类似快速幂m^2logn

前两种做法见:http://wenku.baidu.com/link?url=oUU_lq_wYM37N9QmycWeYXANcoRTT9CcXdTZ8yXznmCMM0meuLF-mmhtq20qQ2hyND9ojWcfLm9ytHK2uS05aj1ICMXnU2giKqGYPgfU7Vm

3)直接构造 m^2递推

见:http://blog.miskcoo.com/2014/06/bzoj-3157(ps:貌似有错 是+号而不是-)

每种做法都没想到T_T

3最好写所以写了3

 1 int n,m,f[maxn],c[maxn][maxn];
 2 inline int power(int x,int y)
 3 {
 4     int t=1;
 5     for(;y;y>>=1,x=(ll)x*x%mod)
 6         if(y&1)t=(ll)t*x%mod;
 7     return t;
 8 }
 9 
10 int main()
11 
12 {
13 
14     freopen("input.txt","r",stdin);
15 
16     freopen("output.txt","w",stdout);
17 
18     n=read();m=read();
19     if(m==1){printf("%lld\n",(ll)n*(n+1)/2%mod);return 0;}
20     c[0][0]=1;
21     for1(i,m)
22     {
23         c[i][0]=c[i][i]=1;
24         for1(j,i-1)c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
25     }
26     int inv=power(m-1,mod-2);
27     f[0]=((ll)(power(m,n+1)-1)*inv-1)%mod;
28     for1(i,m)
29     {
30         int t=0;
31         for0(j,i-1)t=(t+((ll)((i-j)&1?-1:1)*c[i][j]%mod*f[j]%mod))%mod;
32         f[i]=((ll)inv*((ll)power(n,i)%mod*power(m,n+1)%mod+t))%mod;
33     }
34     printf("%d\n",(f[m]+mod)%mod);
35 
36     return 0;
37 
38 }  
View Code

这种题以后碰见能想到这么变换?神题

 UPD:矩阵写法 orzzzzzzzzzzzzz  好像这种方法最好想,因为最暴力orzzzzzzzzzz

 1 ll n,m,p;
 2 inline void mul(matrix x,matrix y,matrix z)
 3 {
 4     matrix t;
 5     memset(t,0,sizeof(t));
 6     for0(i,m+1)
 7      for0(j,m+1)
 8       for0(k,m+1)
 9        t[i][j]=(t[i][j]+x[i][k]*y[k][j])%p;
10     for0(i,m+1)
11      for0(j,m+1)
12        z[i][j]=t[i][j];
13 }
14 matrix a,b,c;
15 void ksm(int y)
16 {
17     for(;y;y>>=1,mul(a,a,a))
18         if(y&1)mul(b,a,b);
19 }
20 
21 int main()
22 
23 {
24 
25     freopen("input.txt","r",stdin);
26 
27     freopen("output.txt","w",stdout);
28 
29     n=read();m=read();p=read();
30     c[0][0]=1;
31     for1(i,m)
32     {
33         c[i][0]=c[i][i]=1;
34         for1(j,i-1)c[i][j]=(c[i-1][j-1]+c[i-1][j])%p;
35     }
36     for0(i,m)
37      for0(j,i)
38       a[j][i]=m*c[i][j]%p;
39     a[m][m+1]=a[m+1][m+1]=1;
40     for0(i,m+1)b[i][i]=1;
41     ksm(n);
42     for0(i,m)a[0][i]=m;a[0][m+1]=0;
43     mul(a,b,a);
44     cout<<a[0][m+1]<<endl;
45 
46     return 0;
47 
48 }  
View Code

 POJ1830开关问题

解异或方程组比线性的更好写。

不过不保证有解就得多加一些东西。。。

直接看代码更容易理解

 1 int n,ans,a[50][50];
 2 inline void gauss()
 3 {
 4     int i,j,k;
 5     for(i=1,j=1;j<=n;i++,j++)
 6     {
 7         for(k=i;!a[k][j]&&k<=n;k++);
 8         if(k>n){i--;continue;}
 9         for2(x,j,n+1)swap(a[i][x],a[k][x]);
10         for2(x,i+1,n)if(a[x][j])
11             for2(y,j,n+1)a[x][y]^=a[i][y];
12     }
13     for(j=i;j<=n;j++)if(a[j][n+1]){printf("Oh,it's impossible~!!\n");return;}
14     printf("%d\n",1<<(n-i+1));
15 }
16 
17 int main()
18 
19 {
20 
21     freopen("input.txt","r",stdin);
22 
23     freopen("output.txt","w",stdout);
24     int T=read();
25     while(T--)
26     {
27 
28       n=read();
29       memset(a,0,sizeof(a));
30       for1(i,n)a[i][n+1]=read(),a[i][i]=1;
31       for1(i,n)a[i][n+1]^=read();
32       while(1)
33       {
34           int x=read(),y=read();
35           if(!x&&!y)break;
36           a[y][x]=1;
37       }
38       gauss();
39     }
40 
41     return 0;
42 
43 }  
View Code

 BZOJ2466: [中山市选2009]树

自由元的意思是无论取什么值,都存在一种合法的赋值满足所有方程。

而哪些非自由元呢?它们的取值是受自由元取值的影响的。

自由元不确定的话,它们的值也无法知道,因为方程数目不够。

所以对于此题我们爆搜出所有合法的解,然后取最小个数。

 1 int n,m,tot,ans,a[200][200],b[200];
 2 inline void gauss()
 3 {
 4     for1(i,n)
 5     {
 6         int k=i;
 7         while(k<=n&&!a[k][i])k++;
 8         if(k>n)continue;
 9         for2(j,i,n+1)swap(a[i][j],a[k][j]);
10         for2(j,i+1,n)if(a[j][i])
11             for2(k,i,n+1)
12              a[j][k]^=a[i][k];
13     }
14 }
15 inline void dfs(int x)
16 {
17     if(tot>=ans)return;
18     if(!x){ans=min(ans,tot);return;}
19     if(a[x][x])
20     {
21         b[x]=a[x][n+1];
22         for2(i,x+1,n)if(a[x][i])b[x]^=b[i];
23         if(b[x])tot++;
24         dfs(x-1);
25         if(b[x])tot--;
26     }else 
27     {
28         b[x]=0;dfs(x-1);
29         b[x]=1;tot++;dfs(x-1);tot--;
30     }
31 }
32 
33 int main()
34 
35 {
36 
37     freopen("input.txt","r",stdin);
38 
39     freopen("output.txt","w",stdout);
40 
41     while(1)
42     {
43         n=read();if(!n)break;
44         tot=0;ans=inf;
45         memset(a,0,sizeof(a));
46         memset(b,0,sizeof(b));
47         for1(i,n)a[i][i]=1,a[i][n+1]=1;
48         for1(i,n-1){int x=read(),y=read();a[x][y]=a[y][x]=1;}
49         gauss();dfs(n);
50         printf("%d\n",ans);
51     }
52 
53     return 0;
54 
55 }  
View Code

 

BZOJ3866: The Romantic Hero

简单的背包DP。因为是方案数所以把初值及什么都不取得去掉。用方案的增量来更新答案。

细节不少。。。

 1 int a[maxn],f[maxn][maxn],g[maxn][maxn];
 2 int main()
 3 {
 4     freopen("input.txt","r",stdin);
 5     freopen("output.txt","w",stdout);
 6     int T=read();
 7     while(T--)
 8     {
 9         int n=read(),ans=0;
10         for1(i,n)a[i]=read();
11         memset(g[n+1],0,sizeof(g[n+1]));
12         g[n+1][1023]=1;
13         for3(i,n,2)
14         {
15          for0(j,1023)g[i][j]=g[i+1][j];
16          for0(j,1023)g[i][j&a[i]]=(g[i][j&a[i]]+g[i+1][j])%mod;
17         }
18         for3(i,n,2)g[i][1023]--;
19         f[0][0]=1;
20         for1(i,n-1)
21         {
22          for0(j,1023)ans=(ans+(ll)f[i-1][j]*g[i+1][j^a[i]]%mod)%mod;        
23          for0(j,1023)f[i][j]=(f[i-1][j]+f[i-1][j^a[i]])%mod;
24         }
25         printf("%d\n",ans);
26     }      
27     return 0;
28 }
View Code

 

BZOJ3789: 扫雪车

有环对答案有没有影响?没环的话肯定直接下界最大流就可以了。

 1 int  n,m,s,t,ss,tt,sum,maxflow,tot=1,head[maxn],cur[maxn],h[maxn];
 2 queue<int>q;
 3 struct edge{int go,next,v;}e[maxm];
 4 void add(int x,int y,int v)
 5 {
 6     e[++tot]=(edge){y,head[x],v};head[x]=tot;
 7     e[++tot]=(edge){x,head[y],0};head[y]=tot;
 8 }
 9 void insert(int x,int y,int l,int r)
10 {
11     if(l){add(ss,y,l);add(x,tt,l);}
12     add(x,y,r-l);
13 }
14 bool bfs()
15 {
16     for(int i=0;i<=n+1;i++)h[i]=-1;
17     q.push(s);h[s]=0;
18     while(!q.empty())
19     {
20         int x=q.front();q.pop();
21         for(int i=head[x];i;i=e[i].next)
22          if(e[i].v&&h[e[i].go]==-1)
23          {
24             h[e[i].go]=h[x]+1;q.push(e[i].go);
25          }
26     }
27     return h[t]!=-1;
28 }
29 int dfs(int x,int f)
30 {
31     if(x==t) return f;
32     int tmp,used=0;
33     for(int i=cur[x];i;i=e[i].next)
34      if(e[i].v&&h[e[i].go]==h[x]+1)
35     {
36         tmp=dfs(e[i].go,min(e[i].v,f-used));
37         e[i].v-=tmp;if(e[i].v)cur[x]=i;
38         e[i^1].v+=tmp;used+=tmp;
39         if(used==f)return f;       
40     }
41     if(!used) h[x]=-1;
42     return used;
43 }
44 void dinic()
45 {
46     maxflow=0;
47     while(bfs())
48     {
49         for (int i=0;i<=n+1;i++)cur[i]=head[i];maxflow+=dfs(s,inf);
50     }
51 }
52 int main()
53 {
54     freopen("input.txt","r",stdin);
55     freopen("output.txt","w",stdout);
56     n=read();m=read();s=read();t=read();ss=0;tt=n+1;
57     while(m--)
58     {
59         int x=read(),y=read(),r=read(),l=read();
60         insert(x,y,l*r,r);
61         sum+=l*r;
62     }
63     insert(t,s,0,inf);
64     swap(s,ss);swap(t,tt);
65     dinic();
66     if(maxflow!=sum){printf("0\n");return 0;}
67     swap(s,ss);swap(t,tt);
68     dinic();
69     printf("%d\n",maxflow);
70     return 0;
71 }
View Code

 

BZOJ2460: [BeiJing2011]元素

同CQOINIM游戏

 1 int n,ans;
 2 ll b[maxn];
 3 struct rec{ll x;int y;}a[maxn];
 4 inline bool cmp(rec a,rec b){return a.y>b.y;}
 5 int main()
 6 {
 7     freopen("input.txt","r",stdin);
 8     freopen("output.txt","w",stdout);
 9     n=read();
10     for1(i,n)a[i].x=read(),a[i].y=read();
11     sort(a+1,a+n+1,cmp);
12     for1(i,n)
13     {
14         for3(j,63,0)
15          if(a[i].x>>j&1)
16           {
17               if(b[j])a[i].x^=b[j];
18               else {b[j]=a[i].x;break;}
19           }
20         if(a[i].x)ans+=a[i].y;
21     }
22     cout<<ans<<endl;
23     return 0;
24 }
View Code

 

BZOJ1342: [Baltic2007]Sound静音问题

单调队列水。。。


 1 int n,m,k,a[maxn],q[2][maxn],l[2],r[2];
 2 
 3 int main()
 4 
 5 {
 6 
 7     freopen("input.txt","r",stdin);
 8 
 9     freopen("output.txt","w",stdout);
10 
11     n=read();m=read();k=read();
12     for1(i,n)a[i]=read();
13     l[0]=l[1]=1;
14     bool flag=0;
15     for1(i,n)
16     {
17         while(l[0]<=r[0]&&a[q[0][r[0]]]<a[i])r[0]--;
18         q[0][++r[0]]=i;
19         while(l[1]<=r[1]&&a[q[1][r[1]]]>a[i])r[1]--;
20         q[1][++r[1]]=i;
21         while(l[0]<r[0]&&i-q[0][l[0]]>=m)l[0]++;
22         while(l[1]<r[1]&&i-q[1][l[1]]>=m)l[1]++;
23         if(i>=m&&a[q[0][l[0]]]-a[q[1][l[1]]]<=k)printf("%d\n",i-m+1),flag=1;
24     }
25     if(!flag)printf("NONE\n");
26 
27     return 0;
28 }
View Code

BZOJ 1370: [Baltic2003]Gang团伙

水并查集,刚开始把朋友的敌人也合并了。。。

 1 int n,m,fa[maxn],ans;
 2 inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
 3 inline void bing(int x,int y)
 4 {
 5     int xx=find(x),yy=find(y);
 6     fa[yy]=xx;
 7 }
 8 
 9 int main()
10 
11 {
12 
13     freopen("input.txt","r",stdin);
14 
15     freopen("output.txt","w",stdout);
16 
17     n=read();m=read();
18     for1(i,n<<1)fa[i]=i;
19     for1(i,m)
20     {
21         char ch=getchar();
22         while(ch!='F'&&ch!='E')ch=getchar();
23         int x=read(),y=read();
24         if(ch=='F')bing(x,y);//bing(x+n,y+n);
25         else bing(x,y+n),bing(y,x+n);
26     }
27     for1(i,n)if(fa[i]==i)ans++;
28     cout<<ans<<endl;
29 
30     return 0;
31 
32 } 
View Code

BZOJ1316: 树上的询问

比2599还简单。。。


 1 struct edge{int go,next,w;}e[2*maxn];
 2 int n,m,cnt1,cnt2,tot,sum,rt,b[maxn],a[maxn],f[maxn],g[maxm],d[maxn],head[maxn],s[maxn];
 3 bool v[maxn];
 4 inline void insert(int x,int y,int z)
 5 {
 6     e[++tot]=(edge){y,head[x],z};head[x]=tot;
 7     e[++tot]=(edge){x,head[y],z};head[y]=tot;
 8 }
 9 inline void getrt(int x,int fa)
10 {
11     s[x]=1;f[x]=0;
12     for(int i=head[x],y;i;i=e[i].next)if(!v[y=e[i].go]&&y!=fa)
13     {
14         getrt(y,x);
15         s[x]+=s[y];
16         f[x]=max(f[x],s[y]);
17     }
18     f[x]=max(f[x],sum-f[x]);
19     if(f[x]<f[rt])rt=x;
20 }
21 inline void getdep(int x,int fa,int w)
22 {
23     d[++cnt2]=w;
24     for4(i,x)if(!v[y]&&y!=fa)getdep(y,x,w+e[i].w);
25 }      
26 inline void work(int x)
27 {
28     v[x]=1;cnt1=0;cnt2=0;
29     for4(i,x)if(!v[y])
30     {
31         getdep(y,x,e[i].w);
32         for2(j,cnt1+1,cnt2)for1(k,m)if(d[j]<=a[k])b[k]|=g[a[k]-d[j]];
33         for2(j,cnt1+1,cnt2)if(d[j]<=1000000)g[d[j]]=1;
34         cnt1=cnt2;
35     }
36     for1(i,m)b[i]|=g[a[i]];
37     for1(i,cnt2)if(d[i]<=1000000)g[d[i]]=0;
38     for4(i,x)if(!v[y])
39     {
40         sum=s[y];rt=0;
41         getrt(y,x);
42         work(rt);
43     }
44 }
45 int main()
46 {
47     freopen("input.txt","r",stdin);
48     freopen("output.txt","w",stdout);
49     n=read();m=read();
50     for1(i,n-1)
51     {
52         int x=read(),y=read(),z=read();insert(x,y,z);
53     }
54     for1(i,m)a[i]=read();
55     g[0]=1;
56     f[rt=0]=inf;
57     sum=n;
58     getrt(1,0);
59     work(rt);
60     for1(i,m)printf("%s\n",b[i]?"Yes":"No");
61     return 0;
62   
63 }  
View Code

 BZOJ2662: [BeiJing wc2012]冻结

破水题WA两发。。。

 1 int n,m,k,head[maxn],d[maxn][55],tot;
 2 struct edge{int go,next,w;}e[2*maxm];
 3 queue<pa>q;
 4 bool v[maxn][15];
 5 inline void add(int x,int y,int w)
 6 {
 7     e[++tot]=(edge){y,head[x],w};head[x]=tot;
 8     e[++tot]=(edge){x,head[y],w};head[y]=tot;
 9 }
10  
11 int main()
12  
13 {
14     freopen("input.txt","r",stdin);
15     freopen("output.txt","w",stdout);
16     n=read();m=read();k=read();
17     for1(i,m)
18     {
19         int x=read(),y=read(),w=read();
20         add(x,y,w);
21     }
22     for1(i,n)for0(j,k)d[i][j]=inf;
23     d[1][0]=0;
24     q.push(pa(1,0));
25     while(!q.empty())
26     {
27         int x=q.front().first,z=q.front().second;q.pop();
28         v[x][z]=0;
29         for4(i,x)
30         {
31             if(d[x][z]+e[i].w<d[y][z])
32             {
33                 d[y][z]=d[x][z]+e[i].w;
34                 if(!v[y][z]){v[y][z]=1;q.push(pa(y,z));}
35             }
36             if(d[x][z]+e[i].w/2<d[y][z+1]&&z<k)
37             {
38                 d[y][z+1]=d[x][z]+e[i].w/2;
39                 if(!v[y][z+1]){v[y][z+1]=1;q.push(pa(y,z+1));}
40             }
41         }
42     }
43     int ans=inf;
44     for0(i,k)ans=min(ans,d[n][i]);
45     cout<<ans<<endl;
46     return 0;
47 }  
View Code

 

posted @ 2015-01-13 13:05  ZYF-ZYF  Views(367)  Comments(0Edit  收藏  举报