【GDOI2017第四轮模拟day2】叶片

来源:互联网 发布:单片机小车轮子掉 编辑:程序博客网 时间:2024/03/29 07:14

Description

一个圆形涡轮上有N 个叶片均匀围成一圈,按顺时针1 到N 标号,其中有一些叶片损坏了。现在要把损坏的叶片给拆下来,但是为了使涡轮正常工作,它的重心还应该落在中心上。求最少还要再拆下几个叶片才能实现目标。

Input

第一行两个整数N,M。M 表示损坏的叶片数目。
接下来一行有M 个数字,分别表示损坏的叶片标号。

Output

输出一行答案。
如果只有拿掉所有叶片才能实现目标那么就输出-1。

Sample Input

3 1
2

Sample Output

-1

Data Constraint

对于20% 的数据, 1 <= N<= 10。
对于100% 的数据, 1 <= M<= N <=20000, 且N 至多包含两个质因子。

题解

题目大意:
现在有很多不同方向的力,有一些力强制不能选,问最多可以选多少个力使得它们的合力为0
数据中有这样一句话:N至多包含两个质因子,设为x,y,观察一下可以发现合力为零就是k,k+x,k+2x….全部都选或者k,k+y,k+2y…全部都选,形成一个类似环的东西,那么模型就变成了:假设选择一个叶片k,那么要么选择方案1,要么选择方案2,不能两个都选择或者两个都不选择
那么我们可以构造一个大小为x*y的矩阵,其中cc[1,j]表示选择了k之后沿着方案x必须要选的,cc[j,k]表示选了cc[j,1]之后沿着方案y必须要选的
可以发现,每一个值会且只会出现在矩阵里面一次
那么我们现在可以全部选择方案x或者全部选择方案y,然后给答案加一个上述两者的较大值

贴代码

var    a:array[0..20005]of longint;    cc:array[0..1005,0..1005]of longint;    vis:array[0..20005]of boolean;    i,j,k,l,m,n,x,y,z,tt1,tt2,ans:longint;    bt:boolean;begin    assign(input,'fan.in'); reset(input);    assign(output,'fan.out'); rewrite(output);    readln(n,m);    for i:=1 to m do    begin        read(x);        vis[x]:=true;    end;    readln;    for i:=2 to n do if n mod i=0 then break;    x:=i;    tt1:=n;    while tt1 mod x=0 do tt1:=tt1 div x;    for i:=2 to n+1 do if (tt1 mod i=0) and (i<>x) then break;    if i=n+1 then y:=1 else y:=i;    for i:=1 to n do    if vis[i]=false then    begin        cc[1,1]:=i;        for j:=2 to x do        begin            cc[j,1]:=cc[j-1,1]+n div x;            if cc[j,1]>n then cc[j,1]:=cc[j,1]-n;        end;        for j:=1 to x do            for k:=2 to y do            begin                cc[j,k]:=cc[j,k-1]+n div y;                if cc[j,k]>n then cc[j,k]:=cc[j,k]-n;            end;        tt1:=0;        tt2:=0;        if y<>1 then        for j:=1 to x do        begin            bt:=false;            for k:=1 to y do if vis[cc[j,k]] then            begin                bt:=true;                break;            end;            if bt=false then tt1:=tt1+y;        end;        if x<>1 then        for j:=1 to y do        begin            bt:=false;            for k:=1 to x do if vis[cc[k,j]] then            begin                bt:=true;                break;            end;            if bt=false then tt2:=tt2+x;        end;        if tt1>tt2 then ans:=ans+tt1 else ans:=ans+tt2;        for j:=1 to x do            for k:=1 to y do vis[cc[j,k]]:=true;    end;    if ans=0 then writeln(-1) else writeln(n-m-ans);    close(input); close(output);end.
0 0
原创粉丝点击