这次考试CE了。

  原因是我改了一个longlong没编译,然后最后查出来的时候已经没时间了。

  不CE的话应该rk7左右。update:因为这个CE把我卡出了第一基房!!!!

  但是都是暴力分。

  T1:是一个规律题,给了5个样例,但我都没看出来,也是废了。我用背包A了

  这个题首先是一道比较屎的背包都能想到。

  但是转移会出错,原因在于:$f[j]|=f[(j-w[i]+k)%k]$这个东西转移顺序出问题了。

  解决办法就是一个转移循环k次。

  复杂度$O(nk^{2})$但是题目给了三个分档,k=100,k=1000,n,k=100000

  首先100的肯定可以。

  1000的就会出问题。但是有一个剪枝就是每次转移的时候转移完看看答案是否变化,如果不变化那么很显然就不用在循环接下来的保证正确性的k次循环。经过实测在100次左右答案就不在变化,复杂度可过。

  100000的nk就死了,那么没办法,n的循环不能省,但是k的循环……,我可以随机找一个容积更新,大概随机次数在200次之后就稳定了。所以。。。。。n*?似乎可过????

  数据貌似卡不了我复杂度,正解$O(nlogn)$,n极限在1e5,然后内层循环能循环250。。,因为他即使是构造的,但我仍是随机看人品更新的

  然后多交两次就A了。

  其实正确率还是蛮高的,在控制使n*k<=25000000的时候接近100%

  n*k<=10000000的时候交3次WA1次。

  

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
using namespace std;
const int N=1000020;
int w[N],a[N],f[N],cnt;
long long rd()
{
    long long s=0,w=1;
    char cc=getchar();
    while(cc<'0'||cc>'9') {if(cc=='-') w=-1;cc=getchar();}
    while(cc>='0'&&cc<='9') s=(s<<3)+(s<<1)+cc-'0',cc=getchar();
    return s*w;
}
int main()
{
    //freopen("math5.in","r",stdin);
    srand(unsigned(time(0)));
    int n=rd(),k=rd();
    for(int i=1;i<=n;i++) a[i]=rd();
    for(int i=1;i<=n;i++)
    {
        if(!f[a[i]%k])
        {
            f[a[i]%k]=1;
            w[++cnt]=a[i]%k;
        }
    }
    int ans=0;
    sort(w+1,w+cnt+1,greater<int>());
    if(n==1)
    {
        int gcd=a[1]%k;
        for(int i=1;i<=k;i++)
            f[1ll*gcd*i%k]=1;
        for(int i=0;i<k;i++)
            ans=ans+f[i];
        printf("%d\n",ans);
        for(int i=0;i<k;i++)
            if(f[i]) printf("%d ",i);
        puts("");
        return 0;
        return 0;
    }
    if(k<=100)
    {
        for(int i=1;i<=cnt;i++)
        {
            for(int p=1;p<=k;p++)
            {
                int sum=0;
                for(int j=0;j<k;j++)
                {
                    f[j]|=f[(j-w[i]+k)%k];
                    sum+=f[j];
                }
                if(ans==sum) break;
                ans=max(ans,sum);
            }
        }
        printf("%d\n",ans);
        for(int i=0;i<k;i++)
            if(f[i])printf("%d ",i);
        puts("");
        return 0;
    }
    else if(k<=1000)
    {
        for(int i=1;i<=cnt;i++)
        {
            for(int p=1;p<=k;p++)
            {
                int sum=0;
                for(int j=0;j<k;j++)
                {
                    f[j]|=f[(j-w[i]+k)%k];
                    sum+=f[j];
                }
                if(sum==ans) break;
                else ans=max(ans,sum);
            }
        }
        printf("%d\n",ans);
        for(int i=0;i<k;i++)
            if(f[i])printf("%d ",i);
        puts("");
        return 0;
    }
    else
    {
        for(register int i=1;i<=cnt;++i)
        {
            for(register int p=1;p*cnt<=25000000;++p)
            {
                const int j=rand()%k;
                f[j]|=f[(j-w[i]+k)%k];
            }
        }
        for(register int i=0;i<k;i++) ans+=f[i];
        printf("%d\n",ans);
        for(register int i=0;i<k;i++)
            if(f[i])printf("%d ",i);
        puts("");
        return 0;
    }
}
/*
g++ -std=c++11 1.cpp -o 1
./1
2 8
4 12
*/
View Code

相关文章: