URAL1765 Error 404

题目描述:

vjudge

题解:

STO ljx OTZ

下面这个算法是这位贡献的。


不妨将删去改为加入。

那么对于$n=p^k$,即只有一个质因子的$n$来说,若$i$已选,那么$i+n/p$、$i+2*n/p$……都必选。

这个先感性理解一下。

根据这个可以$O(n)$出解。

再看$n=p1^{k1}*p2^{k2}$,即有两个质因子。

对于已选点$i$有两种选择,一种是$i+n/p1$、$i+2*n/p1$……都选,另一种是$i+n/p2$、$i+2*n/p2$……都选。

这个可以将原来的$n$个点分成$n/p1/p2$组,每组都两种选择,即要么分$p1$小组,要么分$p2$小组。

时间复杂度貌似也是$O(n)$??!

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 20050;
template<typename T>
inline void read(T&x)
{
    T f = 1,c = 0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
    x = f*c;
}
int n,k,m[10],c;
bool vis[N],vis1[N],vis2[N];
void init()
{
    int n0 = n;
    for(int i=2;i*i<=n0;i++)if(n0%i==0)
    {
        m[++c] = i;
        while(n0%i==0)n0/=i;
    }
    if(n0!=1)m[++c]=n0;
}
int cxk(int x){return x<n?x:x%n;}
int sta[N],tl;
int main()
{
    read(n),read(k);init();
    if(c==1)
    {
        int ans = 0;
        for(int x,i=1;i<=k;i++)
        {
            read(x);x--;vis[x]=1;
            if(!vis1[x])
            {
                vis1[x] = 1;ans += m[1];
                int j = cxk(x+n/m[1]);
                while(j!=x)vis1[j]=1,j=cxk(j+n/m[1]);
            }
        }
        if(ans==n)puts("-1");
        else
        {
            printf("%d
",ans-k);
            for(int i=0;i<n;i++)if(!vis[i]&&vis1[i])
                printf("%d ",i+1);
            puts("");
        }
        return 0;
    }else
    {
        for(int x,i=1;i<=k;i++)
        {
            read(x),x--,vis[x]=1;
            if(!vis1[x])
            {
                for(int j=x,k=1;k<=m[1];j=cxk(j+n/m[1]),k++)vis1[j]=1;
            }
            if(!vis2[x])
            {
                for(int j=x,k=1;k<=m[2];j=cxk(j+n/m[2]),k++)vis2[j]=1;
            }
        }
        for(int i=0;i<n/m[1]/m[2];i++)
        {
            int c1 = 0,c2 = 0;
            for(int j=i,k=1;k<=m[1]*m[2];j=cxk(j+n/m[1]/m[2]),k++)
            {
                if(!vis[j]&&vis1[j])c1++;
                if(!vis[j]&&vis2[j])c2++;
            }
            if(c1<c2)
            {
                for(int j=i,k=1;k<=m[1]*m[2];j=cxk(j+n/m[1]/m[2]),k++)
                    if(!vis[j]&&vis1[j])sta[++tl]=j+1;
            }else
            {
                for(int j=i,k=1;k<=m[1]*m[2];j=cxk(j+n/m[1]/m[2]),k++)
                    if(!vis[j]&&vis2[j])sta[++tl]=j+1;
            }
        }
        if(tl+k==n)puts("-1");
        else
        {
            sort(sta+1,sta+1+tl);
            printf("%d
",tl);
            for(int i=1;i<=tl;i++)
                printf("%d ",sta[i]);
            puts("");
        }
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10872286.html