JZOJ 100024. 【NOIP2016提高A组模拟7.6】数球

Description

小A有n个球,编号分别为1到n,小A每次都会从n个球中取出若干个球,至少取一个,至多取n个,每次取完再放回去,需要满足以下两个条件。
每次取出的球的个数两两不同。
每次取出的球的集合两两不包含。包含是指,对于两次取球,对于取的数目少的那次取球的所有球都出现在取的数目多的那次取球中,例如{1,2}和{1,2,4},{1,2}和{2,3}则不算作包含。
而小A现在突然想知道他最多能进行多少次这样的操作,并希望你能给出具体的取球方案。

Input

一个整数n。

Output

第一行一个数k,表示能进行的最多次数。
接下来k行,每行第一个整数p,表示这次取的球数,接下来p个数表示这次取的球的编号,编号只需要不同,不需要按照顺序输出,本题设有spj。
对于每个测试点,每组数据第一行正确可以获得20%的分,如果第一行和方案均正确获得100%的分。

Sample Input

4

Sample Output

2
1 1
2 3 4

Data Constraint

对于30%的数据,n<=7。
对于50%的数据,n<=20。
对于70%的数据,n<=100。
对于100%的数据,4<=n<=1000。

Solution

  • 这题我们可以采用构造法,构造出合法的取球方案。

  • 显然,答案必为 N2 (1~N-2 的取球方案)。

  • 事实上我们可以两个两个跳着处理,假设我们已经得出了 1 到 N-2 的答案,要求 N 的答案。

  • 那么就有原答案的长度为 1~N-4 ,可填的两个数分别是 N 和 N-1

  • 为了避免“包含”,我们在每行末尾都加上一个 N 。

  • 那这样答案就的长度就变成了 2~N-3 ,之后 1 的位置就填上 N-1 。

  • 最后一行填 1~N-2 ,这样显然是不会出现“包含”情况的。(不懂可以找数尝试)

  • 那么这样时间复杂度就是 O(N2)

Code

#include<cstdio>
using namespace std;
const int N=1000;
int n,num;
int f[N*2][N];
inline void write(int x)
{
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
int main()
{
    scanf("%d",&n);
    write(n-2),putchar('\n');
    f[num=N][0]=f[N][1]=1;
    if(n&1)
        for(int i=5;i<=n;i+=2)
        {
            num--;
            f[num][f[num][0]=1]=i-1;
            for(int j=num+1;j<=num+i-4;j++) f[j][++f[j][0]]=i;
            for(int j=1;j<=i-2;j++) f[num+i-3][j]=j;
            f[num+i-3][0]=i-2;
        }
    else
    {
        f[num+1][0]=2;
        f[num+1][1]=2,f[num+1][2]=3;
        for(int i=6;i<=n;i+=2)
        {
            num--;
            f[num][f[num][0]=1]=i-1;
            for(int j=num+1;j<=num+i-4;j++) f[j][++f[j][0]]=i;
            for(int j=1;j<=i-2;j++) f[num+i-3][j]=j;
            f[num+i-3][0]=i-2;
        }
    }
    for(int i=num;i<num+n-2;i++)
    {
        write(f[i][0]);
        for(int j=1;j<=f[i][0];j++) putchar(' '),write(f[i][j]);
        putchar('\n');
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值