题解#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 }
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 }
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 }
这种题以后碰见能想到这么变换?神题
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }