雅礼中学考试第一场 20180105
先把题目和题解贴上去。
T1就不多说明了,没什么意思,以为很难,拿到题目的时候慌了一会,
思考了一会后,发现就是贪心。
代码如下,一次AC
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstring> 2 #include<cmath> 3 #include<cstdio> 4 #include<iostream> 5 #include<algorithm> 6 7 using namespace std; 8 inline int read() 9 { 10 int x=0,f=1;char ch=getchar(); 11 while(ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();} 12 while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} 13 return x*f; 14 } 15 16 17 int n; 18 char ch[100007]; 19 int a[100007]; 20 21 bool check() 22 { 23 for (int i=1;i<=n/2;i++) 24 if (a[i]!=a[n-i+1]) return false; 25 return true; 26 } 27 bool jt() 28 { 29 int x=a[1],y=a[2]; 30 for (int i=3;i<=n;i++) 31 { 32 if (i%2==1) 33 { 34 if (x!=a[i]) return false; 35 } 36 else 37 { 38 if (y!=a[i]) return false; 39 } 40 } 41 return true; 42 } 43 bool yy() 44 { 45 for (int i=2;i<=n;i++) 46 if (a[i]!=a[i-1]) return false; 47 return true; 48 } 49 bool zj() 50 { 51 for (int i=2;i<=n/2;i++) 52 { 53 if (a[i]!=a[i-1]||a[n-i+2]!=a[n-i+1]) return false; 54 } 55 return true; 56 } 57 int main() 58 { 59 freopen("string.in","r",stdin); 60 freopen("string.out","w",stdout); 61 62 int T=read(); 63 while(T--) 64 { 65 n=read(); 66 scanf("%s",ch+1); 67 for (int i=1;i<=n;i++) 68 a[i]=ch[i]-'0'; 69 if (!check()) printf("1\n"); 70 else 71 { 72 if (jt()||yy()||zj()) printf("-1\n"); 73 else printf("2\n"); 74 } 75 } 76 }
T2
涨了知识吧,发现以前最最小割是真的不理解,通过这道题目有了更深的理解。
割了表示需要这里的花费。
所以S表示负的源点,T表示正的原点,割去与S相连的边就需要负的代价
T表示改点选了正点,这么选的代价就是h中的意义
然后发现答案一定未w的倍数,所以开始可以用系数来解决这道题目,
网络流不能流负边,那么就假设都取了负数,然后割了正的话讲边权改为两倍即可。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cmath> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstdio> 5 #include<cstring> 6 #include<queue> 7 8 #define N 507 9 #define M 20007 10 #define inf 1000000007 11 #define ll long long 12 using namespace std; 13 inline int read() 14 { 15 int x=0,f=1;char ch=getchar(); 16 while(ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();} 17 while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} 18 return x*f; 19 } 20 21 int n,w,p,q,S,T; 22 int cnt,cur[N],hed[N],rea[M],val[M],nxt[M]; 23 int dis[N],u[N]; 24 ll ans; 25 26 void add(int u,int v,int z) 27 { 28 nxt[++cnt]=hed[u]; 29 hed[u]=cnt; 30 rea[cnt]=v; 31 val[cnt]=z; 32 } 33 bool bfs() 34 { 35 memset(dis,-1,sizeof(dis)); 36 dis[S]=0;queue<int>q;q.push(S); 37 while(!q.empty()) 38 { 39 int u=q.front();q.pop(); 40 for (int i=hed[u];i!=-1;i=nxt[i]) 41 { 42 //cout<<"i="<<i<<endl; 43 int v=rea[i],fee=val[i]; 44 if (dis[v]!=-1||!fee)continue; 45 dis[v]=dis[u]+1; 46 if (v==T) return 1; 47 q.push(v); 48 } 49 } 50 return 0; 51 } 52 ll dfs(int u,int MX) 53 { 54 if (!MX||u==T) return MX; 55 ll res=0; 56 for (int i=cur[u];i!=-1;i=nxt[i]) 57 { 58 // if (i!=0) cout<<"i="<<i<<endl; 59 int v=rea[i],fee=val[i]; 60 // cout<<v<<" "<<fee<<endl; 61 if (dis[v]!=dis[u]+1)continue; 62 int x=dfs(v,min(MX,fee)); 63 val[i]-=x,val[i^1]+=x; 64 cur[u]=i; 65 if (x) 66 { 67 MX-=x,res+=x; 68 if (!MX)break; 69 } 70 } 71 if (!res)dis[u]=-1; 72 return res; 73 } 74 void dinic() 75 { 76 while(bfs()) 77 { 78 // cout<<1<<endl; 79 for (int i=S;i<=T;i++)cur[i]=hed[i]; 80 /*for (int i=1;i<=cnt;i++)cout<<nxt[i]<<" "; 81 cout<<endl;*/ 82 ans+=dfs(S,inf); 83 // cout<<2<<endl; 84 } 85 } 86 int main() 87 { 88 int Cas=read(); 89 while(Cas--) 90 { 91 cnt=1,memset(hed,-1,sizeof(hed)); 92 n=read(),w=read(),p=read(),q=read(),S=0,T=n+1; 93 for (int i=1;i<=n;i++)u[i]=1; 94 for (int i=1;i<=p;i++) 95 { 96 int x=read(),y=read(),z=read(),a=read(),b=read(),c=read(),d=read(),e=read(),f=read(); 97 add(x,y,2*a),add(y,x,0); 98 add(y,x,2*a),add(x,y,0); 99 add(y,z,2*b),add(z,y,0); 100 add(z,y,2*b),add(y,z,0); 101 add(z,x,2*c),add(x,z,0); 102 add(x,z,2*c),add(z,x,0); 103 u[x]+=d-f; 104 u[y]+=e-d; 105 u[z]+=f-e; 106 } 107 for (int i=1;i<=q;i++) 108 { 109 int x=read(),y=read(),z=read(); 110 if (z==1) 111 { 112 add(x,y,inf),add(y,x,0); 113 add(y,x,inf),add(x,y,0); 114 } 115 else if (z==2) 116 { 117 add(x,T,inf),add(T,x,0); 118 add(S,y,inf),add(y,S,0); 119 } 120 else add(x,y,inf),add(y,x,0); 121 } 122 for (int i=1;i<=n;i++) 123 { 124 ans-=abs(u[i]); 125 if (u[i]>0) add(i,T,2*u[i]),add(T,i,2*u[i]); 126 else add(S,i,-2*u[i]),add(i,S,0); 127 } 128 dinic(); 129 printf("%lld\n",(ll)ans*w); 130 ans=0; 131 } 132 }
T3
题解解释的很清楚了。
发现一定是小的会赢,不管怎么,大的赢至少有奇数,偶数,不可能稳赢。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstring> 2 #include<cmath> 3 #include<iostream> 4 #include<algorithm> 5 #include<cstdio> 6 7 #define ll long long 8 #define mod 1000000007 9 using namespace std; 10 inline int read() 11 { 12 int x=0;char ch=getchar(); 13 while(ch<'0'||ch>'9'){ch=getchar();} 14 while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} 15 return x; 16 } 17 18 int n,a,b; 19 ll ans[4],num[4]; 20 bool flag; 21 22 inline ll ksm(ll a,int b) 23 { 24 ll ans=1; 25 while(b) 26 { 27 if (b&1)(ans*=a)%=mod; 28 (a*=a)%=mod; 29 b>>=1; 30 } 31 return ans; 32 } 33 int main() 34 { 35 n=read(),a=read(),b=read(); 36 if (a>b) swap(a,b),flag=1; 37 for (int i=1;i<=n;i++) 38 { 39 int x=read()%(a+b); 40 num[(x>=a)+(x>=b)+(x>=b&&x>=2*a)]++; 41 } 42 ans[0]=((ll)(ksm(2,num[1])-1)*ksm(2,num[2]+num[3]))%mod;//(2)存在就a必胜 43 (ans[0]+=(ll)(ksm(2,num[3])-num[3]-1+mod)*ksm(2,num[2]))%=mod;//存在两个xi>=2*a,a必胜,取了一次后就是(2),a必胜。 44 (ans[0]+=(ll)num[3]*(num[2]?ksm(2,num[2]-1):0))%=mod;//2a<=xi一个,并且奇数个(3)a,必胜。 45 ans[2]=((num[2]?ksm(2,num[2]-1):0)+(ll)num[3]*(num[2]?ksm(2,num[2]-1):1))%mod; 46 ans[3]=(num[2]?ksm(2,num[2]-1):1); 47 for (int i=0;i<4;i++) 48 ans[i]=(ll)ans[i]*ksm(2,num[0])%mod;//最后乘上num[0]表示随便取。 49 if (flag) swap(ans[0],ans[1]); 50 for (int i=0;i<3;i++)printf("%lld ",ans[i]);printf("%lld\n",ans[3]); 51 }