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

题目大意

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

解题思路

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

code

#include
#include
#define min(a,b) ((a
#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;
}

你可能感兴趣的:(jzoj)