HDU 6616 Divide the Stones

Face questions

Time limit 3000 ms

Memory limit 131072 kB

Special judge Yes

OS Windows

Chinese 题意

The \ (n-\) stones into \ (K \) stacks, each stack required and is equal to the weight of the stone. Whether the output requirements can be achieved. If it can achieve, but also the output of each stack stone in weight of each stone

Competition horrors

The first reaction on seeing the stadium --dp? will not. Then on the first teammates to throw a little thinking, writing another road Chairman tree (this title) to go. Chairman of the tree wrote half, think of the subject in one condition, k n is a factor, then think of \ (\ frac {n} { k} \) is an integer, then think of the magic square, so just this question and teammates say a moment to be thinking about the direction of the magic square, then teammate heard that there is no magic square, so I followed my TLE Chairman of the tree, until the end there is no a, the other two teammates had just two questions did not just come out, including this problem. The last two questions dismal.

After the game up questions, questions which make up decomposition of the quality factor teammates found that there is a loop variable \ (i \) have a place to forget to add a ...... I listened to the other teams say that the question of the solution of the Chairman of the tree, Zhi Ma himself stupid, it is up to \ (169 \) is \ (k \) cheated.

My idea of ​​a dead end

我们先令\(m=\frac{n}{k}\)。这里有一个结论(貌似这题的解法可以当做这个结论的构造性的证明?)——对于这个分石头的问题,如果石头总重量能被k整除,即每一堆石头重量都是整数,\(k|\frac{(1+n)\times n}{2}\),那么一定存在一个解,使得这\(k\)堆石头,每堆石头都是\(m\)块。

应用这个结论,题意就变成了,让我们把\(1\)~\(n\)总共\(n\)个数字填入\(k\)\(m\)列的矩阵中,使得矩阵每一行之和相等。

设每一堆石头重量\(w=\frac{(1+n)\times n}{2k}=\frac{(1+n)\times m}{2}\)

\(m\)是偶数的情况

此时\(n\)是偶数,那么\(1\)~\(n\)可以两两配对成\(\frac{n}{2}\)对重量为\(n+1\)的石头对。那么我们就可以把这些石头对两个两个地放进矩阵,填完一行填下一行,填满\(k\)行就完事了。为了更方便地用代码实现,我们可以蛇形填数字,像下面这样——

1 8 9 16
2 7 10 15
3 6 11 14
4 5 12 13

\(m\)是奇数的情况

k是偶数

由于\(k\times m=n\),则\(n\)是偶数,\((n+1)\)是奇数,\(w=\frac{(1+n)\times m}{2}\),由于\(m\)也是奇数,所以每堆石头重量不是整数,无解。

k是奇数

\(w=\frac{(1+n)\times m}{2}\)是整数(\(n+1\)是偶数),由上文的结论可知,这是有解的。

幻方的思路(想复杂了还走不通)
  • 如果\(m\geqslant k\),就是矩阵在横着的方向更长的情况,那么可以把前\(k\times k\)个数字按照奇数阶幻方的方式填入矩阵左边\(k\times k\)的部分。剩下\((n-k\times k)\)个石头数量是偶数,要填入矩阵右边\(k\)\(m-k\)列,而\(m-k\)是偶数(奇数减奇数等于偶数),于是问题转化为\(m\)是偶数的情况,蛇形填就好。

  • 如果\(m\leqslant k\),就是矩阵竖着的方向更长的情况,先说我xjb搞出来的结论——使用幻方无解。下面的推导感觉价值不大

    先摸索一番,如果是像上一种情况,把前\(m\times m\)个数字填进矩阵上方部分,那么剩下的数字都大于上方用过的\(m^2\)个,产生的石头堆超重了。于是想着调整一下,求出幻方以后,将幻方内的数字全部增加一个固定的数,使得幻方内数字的值域正好在\([1,n]\)的正中间,那么填完幻方剩下的数字就可以两两配对了。这就差不多转化成了\(m\)是奇数、\(k\)是偶数的情况。下面的推导十分不严谨,漏洞百出……先留坑,以后完善一下吧。

    但和\(m\)是奇数、\(k\)是偶数的情况有点区别,这里的总和不是\(\frac{(1+n)\times n}{2}\),有\(\frac{n-m^2}{2}\)个数字增大了\((m^2+\frac{n-m^2}{2})\),所以剩下的数字总和变成了\[\frac{(1+n)\times n}{2}+\frac{n-m^2}{2}\times (m^2+\frac{n-m^2}{2})\]

    \[=\frac{(1+n)\times n}{2}+\frac{n-m^2}{2}\times \frac{n+m^2}{2}\]

    \[=\frac{2n+3n^2-m^2}{4}\]

    现在我们的目的是,把这\(n-m^2\)个数字分成\(k-m\)行,每行数字之和相等。那么每行的数字之和应该是

    \[w=\frac{2n+3n^2-m^2}{4(k-m)}\]

    \(k=\frac{n}{m}\)代入,整理 不想整理了 可得

    \[w=\frac{2nm+3n^2m-m^3}{4n-4m^2}\]

    如果能实现要求,那么\(w\)还应该满足最基本的条件\(w=\frac{(1+n)\times m}{2}\)。于是把这两个联立起来试试(开始xjb搞,各种不严谨)

    \[\frac{2nm+3n^2m-m^3}{4n-4m^2}=\frac{(1+n)\times m}{2}\]

    整理得

    \[2nm+3n^2m-m^3==2nm-2m^3+2n^2m-2nm^3\]

    \[n^2==-m^2-2nm^2\]

    因为\(n\)\(m\)都是正数,所以上式不成立。所以这种情况使用幻方无解。

题解的思路

先把\(m=1\)的情况特判了。

对于\(m\)是偶数的情况,可以用我上面那个蛇形填的办法。

对于\(m\)是奇数的情况,题解的做法有点玄学,还没仔细证明过——

  • 首先把矩阵的最左边三列用\([1,3k]\)这些数填满
  • 然后留下的右边部分就转化成了\(m\)是偶数的情况,蛇形填。

看不懂题解,最大的问题在于,左边这三列怎么填……题解也不说,咱也没机会问。

查了其他很多人的博客,他们都把这步一笔带过了……于是把代码复制下来,手动输入数据,看输出找规律。规律是挺明显的——

5行的情况

1 8 15
2 10 12
3 7 14
4 9 11
5 6 13

7行的情况

1 11 21
2 14 17
3 10 20
4 13 16
5 9 19
6 12 15
7 8 18

第一列顺着写下来,第二列和第三列从下到上,步长为2。还没想过为啥这是对的……先留坑

另一些思路

来自集训队队长的博客

源代码

这个是题解的思路

#include<queue>
#include<cstdio>

int T;
long long n, k;
std::queue<int> ma[100010];
int main()
{
    // freopen("test.in","r",stdin);
    scanf("%d", &T);
    while(T--)
    {
        scanf("%lld%lld", &n, &k);
        long long sum=(1+n)*n>>1;
        if(k!=1&&k==n||sum%k)
        {
            puts("no");
            continue;
        }
        puts("yes");
        for(int i=1;i<=k;i++)
            while(!ma[i].empty()) ma[i].pop();
        long long m=n/k;
        if(m&1)//m为奇数
        {
            for(int i=1;i<=k;i++) ma[i].push(i);
            int id=k+1,row=k;
            for(;id<=3*k&&id<=n;id++,row-=2)//前3列
            {
                while(row<1) row+=k;
                ma[row].push(id);
                if(id%k==0) row--;
            }
            int delta=1;
            for(row=1;id<=n;id++)//后面的蛇形填
            {
                if(row<1)
                {
                    row=1;delta=1;
                }
                else if(row>k)
                {
                    row=k;
                    delta=-1;
                }
                ma[row].push(id);
                row+=delta;
            }
        }
        else//整个蛇形填
        {
            int delta=1,row=1;
            for(int i=1;i<=n;i++)
            {
                if(row<1)
                {
                    row=1;
                    delta=1;
                }
                else if(row>k)
                {
                    row=k;
                    delta=-1;
                }
                ma[row].push(i);
                row+=delta;
            }
        }
        for(int i=1;i<=k;i++)
        {
            while(!ma[i].empty())
            {
                printf("%d ",ma[i].front());//还好不卡行末空格
                ma[i].pop();
            }
            puts("");
        }
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/wawcac-blog/p/11303310.html