题目:

分析:

开始觉得是神仙题。。。

然后发现n最多有2个质因子

这说明sm呢。。。

学过物理的小朋友们知道,当一个物体受多个不同方向相同的力时,只有相邻力的夹角相等,受力就会平衡

于是拆扇叶相当于在风扇上等分角度

考虑贪心的话,就是一次拆越少,也就是角度分越大越好

那就要用到质因子了

先将编号改为(0~n-1)

首先一个质因子p的情况很好处理,当一个扇叶x掉下时,必须拆下y(其中y mod n/p = x mod n/p)的扇叶

于是直接打标记就好了

然后就是2个质因子的情况

那么一个风扇叶如果要下来,那么它所对应的拆卸方式就有两种

而且这两种只能选一种

同类质因数的情况还不会影响。。。

令掉下来的点所对应的两种方案连边

然后会形成一个二分图

每一种方案对应一个代价

然后代价最少。。。

唔。。。

最小割了

写一会调一会中途还差点认为自己想错了

搞了好久。。

代码实现能力太差了。。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm> #define maxn 40005
#define maxm 300005
#define INF 0x3f3f3f3f using namespace std; inline int getint()
{
int num=,flag=;char c;
while((c=getchar())<''||c>'')if(c=='-')flag=-;
while(c>=''&&c<='')num=num*+c-,c=getchar();
return num*flag;
} int n,K,S,T;
int fir[maxn],nxt[maxm],to[maxm],cap[maxm],cnt;
int h[maxn],tp[maxn];
int pri[maxn],np[maxn],cur;
int A,B;
int num[maxn],ans[maxn],vis[maxn],pos[maxn]; inline void newnode(int u,int v,int w)
{to[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt,cap[cnt]=w;}
inline void insert(int u,int v,int w)
{newnode(u,v,w),newnode(v,u,);} inline bool bfs()
{
memset(h,-,sizeof h);
queue<int>Q;h[S]=,Q.push(S);
while(!Q.empty())
{
int u=Q.front();Q.pop();
for(int i=fir[u];i;i=nxt[i])
if(cap[i]&&!~h[to[i]])
{
h[to[i]]=h[u]+,Q.push(to[i]);
if(to[i]==T)return ;
}
}
return ;
} inline int aug(int u,int flow)
{
if(u==T)return flow;
int used=;
for(int i=tp[u];i;i=nxt[i])
{
tp[u]=i;
if(cap[i]&&h[to[i]]==h[u]+)
{
int w=flow-used;
w=aug(to[i],min(cap[i],w));
cap[i]-=w,cap[i^]+=w,used+=w;
if(used==flow)return flow;
}
}
if(!used)h[u]=-;
return used;
} inline int dinic()
{
int num=;
while(bfs())memcpy(tp,fir,sizeof fir),num+=aug(S,INF);
return num;
} inline void init()
{
np[]=;
for(int i=;i<=n;i++)
{
if(!np[i])pri[++cur]=i;
for(int j=;j<=cur&&i*pri[j]<=n;j++)
{
np[i*pri[j]]=;
if(i%pri[j]==)break;
}
}
} inline void dfs(int u)
{
vis[u]=;
for(int i=fir[u];i;i=nxt[i])if(cap[i]&&!vis[to[i]])dfs(to[i]);
} int main()
{
n=getint(),K=getint();
init();
for(A=;A<=cur;A++)if(n%pri[A]==)break;
for(B=A+;B<=cur;B++)if(n%pri[B]==)break;
if(n==){printf("-1\n");return ;}
if(B>cur)
{
A=n/pri[A];
for(int i=;i<=K;i++)
{
int x=getint();ans[x]=;
if(!vis[x])for(int j=(x-)%A+;j<=n;j+=A)vis[j]=;
}
int num=;
for(int i=;i<=n;i++)num+=vis[i];
if(num==n){printf("-1\n");return ;}
printf("%d\n",num-K);
for(int i=,flag=;i<=n;i++)
if(vis[i]&&!ans[i])
{
printf("%d",i);
if((++flag)==num-K)printf("\n");
else printf(" ");
}
}
else
{
A=n/pri[A],B=n/pri[B];
S=A+B+,T=S+,cnt=;
for(int i=;i<=A;i++)num[i]=n/A;
for(int i=;i<=B;i++)num[A+i]=n/B;
for(int i=;i<=K;i++)
{
int x=getint();ans[x]=;
int tmp1=(x-)%A+,tmp2=(x-)%B+A+;
pos[tmp1]=pos[tmp2]=;
num[tmp1]--,num[tmp2]--;
}
for(int i=;i<=n;i++)
{
int tmp1=(i-)%A+,tmp2=(i-)%B+A+;
if(pos[tmp1]&&pos[tmp2])insert(tmp1,tmp2,INF);
}
for(int i=;i<=A;i++)if(pos[i])insert(S,i,num[i]);
for(int i=A+;i<=A+B;i++)if(pos[i])insert(i,T,num[i]);
int sum=dinic();
if(sum==n-K){printf("-1\n");return ;}
printf("%d\n",sum);
dfs(S);
for(int i=;i<=A;i++)if(pos[i]&&!vis[i])for(int j=i;j<=n;j+=A)ans[j]^=;
for(int i=;i<=B;i++)if(pos[i+A]&&vis[i+A])for(int j=i;j<=n;j+=B)ans[j]^=;
for(int i=,flag=;i<=n;i++)
if(ans[i])
{
printf("%d",i);
if((++flag)==sum){printf("\n");break;}
else printf(" ");
}
}
}

最新文章

  1. 使用 HTML5 Canvas 绘制出惊艳的水滴效果
  2. ios swfit 由继承UIButton了解类的构造方法
  3. C语言基础_2
  4. 十位一线专家分享Spark现状与未来----峰会摘录
  5. Linux 经常使用 性能 检测 命令 说明
  6. 使用php实现网站验证码功能【博主推荐】
  7. python学习笔记 python实现k-means聚类
  8. python pdb 调试
  9. .NET Core 学习笔记3&mdash;&mdash;EF Core
  10. 痞子衡嵌入式:第一本Git命令教程(5)- 提交(commit/format-patch/am)
  11. request内置对象
  12. SoapUI link
  13. ODOO v10.0 自动生成财务凭证的科目设置
  14. 8.2.1.3 Range 优化
  15. 制作openstack使用的Ubuntu镜像
  16. 20164317《网络对抗技术》Exp2 后门原理与实践
  17. #JS 异步处理机制的几种方式
  18. 第29天:js-数组添加删除、数组和字符串相互转换
  19. java object 转为 json
  20. Telnet环境变量

热门文章

  1. promise 讲解
  2. 几个关于2-sat的题
  3. POJ1741 点分治模板
  4. oracle 查询含clob 字段慢
  5. 0002 认识HTML(骨架、DOCTYPE、lang、charset)
  6. 洛谷$P2150\ [NOI2015]$寿司晚宴 $dp$
  7. 1069 微博转发抽奖 (20分)C语言
  8. 1059 C语言竞赛 (20 分)C语言
  9. 1061 判断题 (15 分)C语言
  10. 动态代理之 JDK 动态代理