题面

Time limit 3000 ms

Memory limit 131072 kB

Special judge Yes

OS Windows

中文题意

把\(n\)块石头分成\(k\)堆,要求每堆石头的重量之和相等。输出是否可以实现要求。如果可以实现,还要输出每堆石头里每一块石头的重量

比赛惨状

赛场上看见的第一反应——dp?不会。然后就先扔给有点思路队友,写另一道主席树(这题)去了。主席树写到一半,想起来题目里有个条件,k是n的因子,然后想到\(\frac{n}{k}\)是整数,然后想到幻方,于是和刚这题的队友说了一下可以往幻方的方向思考一下,然后队友表示没有听说过幻方,于是我接着TLE我的主席树,直到结束也没A,两个队友刚的另外两题也没刚出来,包括这题。最后两题惨淡收场。

比赛结束后补题,补分解质因数这题的队友发现,有个循环变量\(i\)有个地方忘记加一了……我听着其他队说主席树那题的解法,直骂自己蠢,被最多\(169\)的\(k\)骗了。

我的走不通的思路

我们先令\(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 (m2+\frac{n-m2}{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;
}

HDU 6616 Divide the Stones的更多相关文章

  1. HDU 5783 Divide the Sequence(数列划分)

    p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; font-family: Calibri; font-s ...

  2. hdu多校第四场 1003 (hdu6616) Divide the Stones 机智题

    题意: 给你重量分别为1到n的n个石头,让你分成重量相等,数量也相等的k组,保证k是n的约数.问你能不能分配,如果能,输出具体的分配方案. 题解: 首先,如果1到n之和不能整除k,那么一定不能如题意分 ...

  3. HDU 4573 Throw the Stones(动态三维凸包)(2013 ACM-ICPC长沙赛区全国邀请赛)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4573 Problem Description Remember our childhood? A fe ...

  4. HDU 5783 Divide the Sequence (贪心)

    Divide the Sequence 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5783 Description Alice has a seq ...

  5. hdu 5783 Divide the Sequence 贪心

    Divide the Sequence 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5783 Description Alice has a seq ...

  6. [2019杭电多校第四场][hdu6616]Divide the Stones

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6616 题意是说n个数分别为1-n,将n个数分成k堆,能否满足每堆个数相等,数值之和相等.保证n%k=0 ...

  7. HDU 5783 Divide the Sequence

    Divide the Sequence Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Othe ...

  8. 【贪心】HDU 5783 Divide the Sequence

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5783 题目大意: 把一个N个数的数列拆成若干段,保证每一段的前缀和都非负,求最多能拆成多少段. 题目 ...

  9. HDU 4751 Divide Groups 2013 ACM/ICPC Asia Regional Nanjing Online

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4751 题目大意:判断一堆人能否分成两组,组内人都互相认识. 解题思路:如果两个人不是相互认识,该两人之 ...

随机推荐

  1. 【Linux开发】【Qt开发】tslibs的配置(触摸屏没有,HDMI屏幕):Qt界面响应USB鼠标

    s3c2416   linux qt4.x 由于触摸屏坏了,板子只能用鼠标了,结果以前可以用的现在鼠标突然不能用了 为此交叉编译了qt的多个版本,也换过根文件系统,以为是tslib版本的问题,却发现q ...

  2. k8s--资源控制器

    资源控制器 1.什么是控制器 Kubernetes中内建了很多controller (控制器) ,这些相当于一个状态机,用来控制Pod的具体状态和行为 Pod 的分类 自主式 Pod:Pod 退出了, ...

  3. ubuntu使用iptables 持久化

    iptables 持久化 安装持久化工具apt-get install iptables-persistent Ubuntu 16.04 调用语法netfilter-persistent savene ...

  4. 在搭建Maven项目时导入elasticsearch架包时遇到的问题

    <!-- 使用elasticsearch 需要导入两个包,从网上复制的可能因为有特殊字符报 cvc-complex-type.2.3: Element 'dependency' cannot h ...

  5. 循环结构 :for

    循环结构 :for 循环四要素: 1.初始化条件 2.循环条件 3.循环体 4.迭代条件 格式: for(初始化条件;循环条件;迭代条件){ 循环体; } 执行顺序 :1 -> 2 -> ...

  6. Java 接口和多态练习

    我们鼠标和键盘实现USB接口,那么我们鼠标和键盘就变成了USB设备,这时候我们就可以把它放到笔记本电脑里面去用 package com.biggw.day10.demo07; /** * @autho ...

  7. Python和Js打印心形

    看到一行Python写的代码,会用LovePython输出心形: print('\n'.join([''.join([('LovePython'[(x-y)%10]if((x*0.05)**2+(y* ...

  8. Aniamtion加载动画

    css新增样式Animation的运用 希望可以通过这个案例加深对Animation以及Transform 两大api的认识 效果图如下: 在这里需要注意的是:理应通过发送服务器请求来获取图片,从而达 ...

  9. node静态资源服务器的搭建----访问本地文件夹(搭建可访问静态文件的服务器)

    我们的目标是实现一个可访问静态文件的服务器,即可以在浏览器访问文件夹和文件,通过点击来查看文件. 1.先创建一个文件夹anydoor,然后在该文件夹里npm init一个package.json文件, ...

  10. Linux系统性能测试工具(四)——CPU性能测试工具之super_pi、sysbench

    本文介绍关于Linux系统(适用于centos/ubuntu等)的CPU性能测试工具-sysbench.CPU性能测试工具包括: super_pi: sysbench——不仅可以测试CPU性能,而且可 ...