T1:数论。
<not_complete>
Code:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 inline int in(){ 6 int x=0;bool f=0; char c; 7 for (;(c=getchar())<‘0‘||c>‘9‘;f=c==‘-‘); 8 for (x=c-‘0‘;(c=getchar())>=‘0‘&&c<=‘9‘;x=(x<<3)+(x<<1)+c-‘0‘); 9 return f?-x:x; 10 } 11 int a[16],sum[3],n,m,ct=0,ans,res; 12 bool mk; 13 inline int gcd(int x,int y){ 14 return (!y)?x:gcd(y,x%y); 15 } 16 int main() 17 { 18 n=in();m=in();mk=0; 19 for (int i=1;i<=m;++i){ 20 a[ct]=in();if (a[ct]==1) {printf("0");return 0;} 21 if (!(a[ct]%3)) mk=(mk||a[ct]==3)?1:0,--ct;++ct; 22 }for (int i=0;i<3;++i) sum[i]=n/3; 23 if (n%3==1) ++sum[1]; 24 else if (n%3==2) ++sum[1],++sum[2]; 25 for (int i=1;i<(1<<ct);++i){ 26 int cnt=0,res=1,tmp; 27 for (int j=0;j<ct;++j)if (i&(1<<j)){ 28 if (1ll*res*a[j]/gcd(res,a[j])>1ll*n) {res=-1;break;} 29 res=a[j]/gcd(res,a[j])*res;++cnt; 30 }if (res==-1) continue; 31 tmp=n/res,cnt=(cnt&1)?-1:1; 32 for (int i=0;i<3;++i) sum[i]+=cnt*(tmp/3); 33 if (res%3==1){ 34 if (tmp%3==1) sum[1]+=cnt; 35 else if (tmp%3==2) sum[1]+=cnt,sum[2]+=cnt; 36 }else if (res%3==2){ 37 if (tmp%3==1) sum[2]+=cnt; 38 else if (tmp%3==2) sum[2]+=cnt,sum[1]+=cnt; 39 } 40 }ans=((sum[1]<sum[2])?sum[2]:sum[1]); 41 printf("%d",(mk||(n<3))?ans:ans+1);return 0; 42 }
T2:最大权闭合子图问题,转二分图匹配解决。
可以发现有冲突的格子(x,y)之间,(x+y)的奇偶性一定不同。
考虑将图黑白染色,每个黑色位置向该位置上的马能够控制的格子连边。
对于负权,可以发现不选一定更优,所以可以直接连权值为0的边,即对0取max。
Code:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<queue> 5 #define ME 220005 6 #define MN 20005 7 #define inf 0x7fffffff 8 using namespace std; 9 inline int in(){ 10 int x=0;bool f=0; char c; 11 for (;(c=getchar())<‘0‘||c>‘9‘;f=c==‘-‘); 12 for (x=c-‘0‘;(c=getchar())>=‘0‘&&c<=‘9‘;x=(x<<3)+(x<<1)+c-‘0‘); 13 return f?-x:x; 14 } 15 struct edge{ 16 int to,next,cap; 17 }e[ME]; 18 const int dx[8]={-2,-1,1,2,2,1,-1,-2}; 19 const int dy[8]={1,2,2,1,-1,-2,-2,-1}; 20 int v[MN],head[MN],iter[MN],lev[MN]; 21 int cnt=1,n,m,s,t,sum; 22 inline void ins(int x,int y,int cp){ 23 e[++cnt].to=y;e[cnt].next=head[x];head[x]=cnt;e[cnt].cap=cp; 24 e[++cnt].to=x;e[cnt].next=head[y];head[y]=cnt;e[cnt].cap=0; 25 } 26 inline void bfs(){ 27 queue<int> q;memset(lev,-1,sizeof(lev)); 28 lev[s]=0;q.push(s);while(!q.empty()){ 29 int u=q.front();q.pop(); 30 for (int i=head[u];i;i=e[i].next){ 31 int v=e[i].to; 32 if (lev[v]==-1&&e[i].cap>0) lev[v]=lev[u]+1,q.push(v); 33 } 34 } 35 } 36 inline int dfs(int u,int f){ 37 if (u==t) return f;int used=0; 38 for (int &i=iter[u];i;i=e[i].next){ 39 int v=e[i].to; 40 if (e[i].cap>0&&lev[u]<lev[v]){ 41 int w=dfs(v,min(f-used,e[i].cap)); 42 if (w>0){ 43 e[i].cap-=w;e[i^1].cap+=w;used+=w; 44 if (used==f) return f; 45 } 46 } 47 }return used; 48 } 49 inline int dinic(){ 50 int fl=0;while (1){ 51 bfs();if (lev[t]==-1) return fl; 52 memcpy(iter,head,sizeof(head)); 53 int d;while((d=dfs(s,inf))>0) fl+=d; 54 } 55 } 56 inline bool check(int x,int y){ 57 return ((x>=0)&&(x<n)&&(y>0)&&(y<=m)); 58 } 59 int main() 60 { 61 n=in();m=in();s=0;t=n*m+1; 62 for (int i=0;i<n;++i) 63 for (int j=1;j<=m;++j){ 64 v[i*m+j]=in(),sum+=max(0,v[i*m+j]); 65 if ((i+j)&1) ins(s,i*m+j,max(0,v[i*m+j])); 66 else ins(i*m+j,t,max(0,v[i*m+j])); 67 }for (int i=0;i<n;++i) 68 for (int j=1;j<=m;++j){ 69 if (!((i+j)&1)) continue; 70 for (int k=0;k<8;++k){ 71 int x=i+dx[k],y=j+dy[k]; 72 if (check(x,y)) ins(i*m+j,x*m+y,inf); 73 } 74 }printf("%d",sum-dinic());return 0; 75 }
时间: 2024-12-28 09:41:07