题目:

分析:

开始觉得是神仙题。。。

然后发现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(" ");
}
}
}

20191211 HNOI2017模拟赛 C题的更多相关文章

  1. 20191211 HNOI2017 模拟赛 问题A

    题目: 分析: 好难好难... 下来听神仙讲.. 每一个长度为n-2的prufer序列一一对应一棵大小为n的树... 每个点在序列中的出现次数为该点的度数减一 哦??? ... 哦... prufer ...

  2. 6.28 NOI模拟赛 好题 状压dp 随机化

    算是一道比较新颖的题目 尽管好像是两年前的省选模拟赛题目.. 对于20%的分数 可以进行爆搜,对于另外20%的数据 因为k很小所以考虑上状压dp. 观察最后答案是一个连通块 从而可以发现这个连通块必然 ...

  3. newcoder NOIP提高组模拟赛C题——保护

    我是发了疯才来写这道题的 我如果用写这道题的时间去写dp,我估计我能写上三四道 可怕的数据结构题 题目 这道题的鬼畜之处在于实在是不太好写 我们看到要求离树根尽量的近,所以我们很容易就能想到树上倍增, ...

  4. noip模拟赛 水题

    题目描述 LYK出了道水题. 这个水题是这样的:有两副牌,每副牌都有n张. 对于第一副牌的每张牌长和宽分别是xi和yi.对于第二副牌的每张牌长和宽分别是aj和bj.第一副牌的第i张牌能覆盖第二副牌的第 ...

  5. 2016 10 26考试 NOIP模拟赛 杂题

    Time 7:50 AM -> 11:15 AM 感觉今天考完后,我的内心是崩溃的 试题 考试包 T1: 首先看起来是个贪心,然而,然而,看到那个100%数据为n <= 2000整个人就虚 ...

  6. 6.29 省选模拟赛 坏题 AC自动机 dp 图论

    考场上随手构造了一组数据把自己卡掉了 然后一直都是掉线状态了. 最后发现这个东西不是subtask -1的情况不多 所以就没管无解直接莽 写题有点晚 故没调出来.. 考虑怎么做 容易想到建立AC自动机 ...

  7. 某模拟赛C题 树上路径统计 (点分治)

    题意 给定一棵有n个节点的无根树,树上的每个点有一个非负整数点权.定义一条路径的价值为路径上的点权和-路径上的点权最大值. 给定参数P,我!=们想知道,有多少不同的树上简单路径,满足它的价值恰好是P的 ...

  8. Newnode's NOI(P?)模拟赛 第二题 dp决策单调优化

    其实直接暴力O(n3)DP+O2O(n^3)DP+O_2O(n3)DP+O2​优化能过- CODE O(n3)O(n^3)O(n3) 先来个O(n3)O(n^3)O(n3)暴力DP(开了O2O_2O2 ...

  9. 10.17(山东多校联合模拟赛 day1)

    山东多校联合模拟赛 day1 题不难 rect [问题描述] 给出圆周上的 N 个点, 请你计算出以这些点中的任意四个为四个角,能构成多少个矩形. 点的坐标是这样描述的, 给定一个数组 v[1..N] ...

随机推荐

  1. APK签名替换检测

    APK二次打包的危害 APK二次打包是Android应用安全风险中的一部分, 一般是通过反编译工具向应用中插入广告代码与相关配置,再在第三方应用市场.论坛发布.打包党对移动App带来的危害有以下几种: ...

  2. Java 学习笔记(11)——lambda 表达式

    在写Java代码的时候,如果某个地方需要一个接口的实现类,一般的做法是新定义一个实现类,并重写接口中的方法,在需要使用的时候new一个实现类对象使用,为了一个简单的接口或者说为了一个回调函数就得额外编 ...

  3. Team Foundation Server 2015使用教程【6】:新增权限为读取器的团队

  4. 图解Go里面的sync.Map了解编程语言核心实现源码

    基础筑基 在大多数语言中原始map都不是一个线程安全的数据结构,那如果要在多个线程或者goroutine中对线程进行更改就需要加锁,除了加1个大锁,不同的语言还有不同的优化方式, 像在java和go这 ...

  5. Jmeter官方插件安装

    在正常使用的过程中,当jmeter功能满足不了使用场景时,可以通过安装官方的插件去实现. Jmeter插件管理官网地址: https://jmeter-plugins.org/install/Inst ...

  6. Docker容器Centos容器安装openssh

    前面在部署容器,使用docker容器作为jenkins的Slave节点时,会发现在使用centos作为镜像源拉去容器,不能正常连接,最后是因为centos的sshd的问题 下面专门是centos容器安 ...

  7. 图解leetcode279 —— 完全平方数

    每道题附带动态示意图,提供java.python两种语言答案,力求提供leetcode最优解. 描述: 给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...)使得它们的和等于  ...

  8. 「洛谷P2397」 yyy loves Maths VI (mode) 解题报告

    P2397 yyy loves Maths VI (mode) 题目背景 自动上次redbag用加法好好的刁难过了yyy同学以后,yyy十分愤怒.他还击给了redbag一题,但是这题他惊讶的发现自己居 ...

  9. 「USACO 1.3」 Name That Number 解题报告

    \(注意 该篇题解为本人较早时期写的题解 所以会很傻 直接能用map 以string为下标偏偏要绕弯儿 有时间改一改QAQ\) [USACO1.2]Name That Number 题目描述 在威斯康 ...

  10. 简单聊一聊JS中的循环引用及问题

    本文主要从 JS 中为什么会出现循环引用,垃圾回收策略中引用计数为什么有很大的问题,以及循环引用时的对象在使用 JSON.stringify 时为什么会报错,怎样解决这个问题简单谈谈自己的一些理解. ...