zoukankan      html  css  js  c++  java
  • [ASDFZ]电风扇的重心

    Description

    把一个\(n\)片扇叶的电风扇掉了\(k\)片叶子,问至少还要拆掉几片叶子才能使电风扇的重心回到转轴上,求一种满足条件的方案.

    HINT

    \(n<2\times10^4,n\)有至多2个质因子.

    Solution

    一个状态的重心在转轴上,当且仅当可以把其拆成若干个相邻扇叶的距离相等的状态.
    对于任意一个相邻扇叶的距离相等为\(k\)的状态,可以把其拆成\(x\)个相邻扇叶的距离相等为\(\frac{k}{x}\)的状态\((k|x)\).
    所以对\(n\)分解质因数.
    如果\(n=1\),不可行.
    如果\(n\)只有\(1\)个质因子\(p\),枚举起点,以\(\frac{n}{p}-1\)为间隔,判断每一圈是否完整:不完整,拆掉这圈没掉的;完整,保留.
    如果\(n\)只有\(2\)个质因子\(p_1,p_2\),考虑二分图.
    判断以\(\frac{n}{p_1}-1\)的每一圈\(i\)是否完整,完整的话\((s,i)=p_1\).
    判断以\(\frac{n}{p_2}-1\)的每一圈\(i\)是否完整,完整的话\((i,t)=p_2\).
    对有交点于圈的点集\(x,y:(x,y)=+\infty\).
    求最小割,没被割去的即为保留的.
    判断割去:对于每一条初始容量为\(+\infty\)的边,如果两端点向源/汇的边只有\(1\)条满流,则满流边被割去;如果两端点向源/汇的边都满流,则初始容量大的满流边被割去.

    #include<cmath>
    #include<queue>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define N 20005
    #define M 20000000
    #define INF 20005
    #define min(a,b) (a<b?a:b)
    #define max(a,b) (a>b?a:b)
    using namespace std;
    struct graph{
    	int nxt,to,f;
    }e[M];
    int a[N],f[N],tot[N],g[N<<1],dep[N<<1],p[3],n,k,s,t,cnt;
    bool b[N],v[N];queue<int> q;
    inline int read(){
    	int ret=0;char c=getchar();
    	while(!isdigit(c)) c=getchar();
    	while(isdigit(c)){
    		ret=(ret<<1)+(ret<<3)+c-'0';c=getchar();
    	}
    	return ret;
    }
    inline void addedge(int x,int y,int f){
    	e[++cnt].nxt=g[x];g[x]=cnt;e[cnt].to=y;e[cnt].f=f;
    }
    inline void adde(int x,int y,int f){
    	addedge(x,y,f);addedge(y,x,0);
    }
    inline bool bfs(int u){
    	memset(dep,0,sizeof(dep));
    	q.push(u);dep[u]=true;
    	while(!q.empty()){
    		u=q.front();q.pop();
    		for(int i=g[u];i;i=e[i].nxt)
    			if(e[i].f>0&&!dep[e[i].to]){
    				q.push(e[i].to);
    				dep[e[i].to]=dep[u]+1;
    			}
    	}
    	return dep[t];
    }
    inline int dfs(int u,int f){
    	if(u==t) return f;
    	int ret=0;
    	for(int i=g[u],d;i&&f;i=e[i].nxt)
    		if(e[i].f>0&&dep[e[i].to]>dep[u]){
    			d=dfs(e[i].to,min(e[i].f,f));
    			e[i].f-=d;e[i^1].f+=d;ret+=d;f-=d;
    		}
    	if(!ret) dep[u]=-1;
    	return ret;
    }
    inline int dinic(){
    	int ret=0;
    	while(bfs(s)) ret+=dfs(s,INF);
    	return ret;
    }
    inline bool chk(int i,int l){
    	for(int j=i;j<=n;j+=l)
    		if(b[j]) return false;
    	return true;
    }
    inline void Aireen(){
    	n=read();k=read();
    	if(n==1){
    		puts("-1");return; 
    	}
    	for(int i=1,j;i<=k;++i){
    		j=read();b[j]=true;
    	}
    	for(int i=2,l=n;i<=n&&l>1;++i){
    		if(!(l%i)){
    			while(!(l%i)) l/=i;
    			p[++cnt]=i;
    		}
    	}
    	if(p[2]){
    		cnt=1;s=(n<<1)+1;t=s+1;
    		for(int i=1,l=n/p[1];i<=l;++i)
    			if(chk(i,l)) adde(s,i,p[1]);
    		for(int i=1,l=n/p[2];i<=l;++i)
    			if(chk(i,l)) adde(i+n,t,p[2]);
    		for(int i=1,l=n/p[1];i<=l;++i)
    			if(chk(i,l)) for(int j=i;j<=n;j+=l) f[j]=i;
    		for(int i=1,l=n/p[2];i<=l;++i){
    			for(int j=i;j<=n;j+=l){
    				if(!tot[f[j]]&&f[j]&&chk(i,l)) adde(f[j],i+n,INF);
    				++tot[f[j]];
    			}
    			for(int j=i;j<=n;j+=l) --tot[f[j]];
    		}
    		dinic();
    		for(int i=g[s];i;i=e[i].nxt)
    			if(!(i&1)&&e[i].f){
    				for(int j=e[i].to,l=n/p[1];j<=n;j+=l)
    					b[j]=true;
    			}
    			else v[e[i].to]=true;
    		for(int i=g[t];i;i=e[i].nxt)
    			if((i&1)&&e[i^1].f){
    				for(int j=e[i].to-n,l=n/p[2];j<=n;j+=l)
    					b[j]=true;
    			}
    			else if((i&1)&&!e[i^1].f){
    				for(int j=g[e[i].to];j;j=e[j].nxt)
    					if(v[e[j].to]){
    						for(int o=e[j].to,l=n/p[1];o<=n;o+=l)
    							b[o]=true;
    					}
    			}
    		cnt=0;
    		for(int i=1;i<=n;++i)
    			if(!b[i]) a[++cnt]=i;
    	}
    	else{
    		cnt=0;
    		for(int i=1,l=n/p[1];i<=l;++i)
    			if(!chk(i,l))
    				for(int j=i;j<=n;j+=l)
    					if(!b[j]) a[++cnt]=j,b[j]=true;
    	}
    	if(cnt==n-k){
    		printf("-1");return;
    	}
    	printf("%d\n",cnt);
    	for(int i=1;i<=cnt;++i)
    		printf("%d ",a[i]);
    	printf("\n");
    }
    int main(){
    	freopen("c.in","r",stdin);
    	freopen("c.out","w",stdout);
    	Aireen();
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    

    2017-03-29 00:04:25

  • 相关阅读:
    ARC 117 D
    Maven依赖踩坑记录
    MobaXterm连接本地CentOS7
    Git在IDEA下的常用操作
    mq消息中间件
    nginx的作用
    Git的使用
    docker
    redis
    导出excel
  • 原文地址:https://www.cnblogs.com/AireenYe/p/15609379.html
Copyright © 2011-2022 走看看