【jzoj5089】【GDOI2017第四轮模拟day2】【叶片】

来源:互联网 发布:算法之美 pdf 百度云 编辑:程序博客网 时间:2024/04/27 09:46

题目大意

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

解题思路

对于一个质因子数的叶片,一定均衡分布,而一个叶片可以被两个质因子选,但现在只能被一个选,可以把关联的位置放在一个二维矩阵上,我们只可以保留行或列,保留了行就不能保留列,可以直接算。

code

#include<cstdio>#include<algorithm>#define min(a,b) ((a<b)?a:b)#define fo(i,j,k) for(int i=j;i<=k;i++)#define fd(i,j,k) for(int i=j;i>=k;i--)#define fr(i,j) for(int i=begin[j];i;i=next[i])using namespace std;int const mn=2*1e4+9,inf=1e9;int n,m,a[10],b[10],tag[mn],tag2[mn],f[mn];int main(){    //freopen("fan.in","r",stdin);    //freopen("fan.out","w",stdout);    freopen("d.in","r",stdin);    freopen("d.out","w",stdout);    scanf("%d%d",&n,&m);int x;    fo(i,1,m){        scanf("%d",&x);        tag[x]++;    }    fo(i,1,n)if(tag[i]>1){        int bb;        bb++;    }    int tmp=n;a[2]=1;    fo(i,2,n)if(tmp%i==0){        a[++a[0]]=i;        while(tmp%i==0)tmp/=i;        if(tmp==1)break;    }    if((a[0]==1)&&(a[1]==n)){        printf("-1");        return 0;    }    int cnt=0,cnt2=0,ans=0;b[1]=n/a[1];b[2]=n/a[2];    fo(k,1,n/a[1]/a[2]){        cnt=cnt2=0;        fo(i,0,a[1]-1)f[i]=0;        fo(i,0,a[2]-1){            int ii=(i*b[2]+k-1)%n+1,ok=1;            fo(j,0,a[1]-1){                tag2[ii]=1;                if(tag[ii])f[j]=1,ok=0;                if((ii<1)||(ii>n)){                    int bb;                    bb++;                }                ii=(ii+b[1]-1)%n+1;            }            cnt+=ok;        }        fo(i,0,a[1]-1)cnt2+=!f[i];        if(a[2]==1)cnt2=0;        ans+=max(cnt*a[1],cnt2*a[2]);    }    if(!ans)printf("-1");    else printf("%d",n-m-ans);    return 0;}
0 0