题目链接:http://acm.hdu.edu.cn/showproblem.php?

pid=5355

题面:

Cake

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)

Total Submission(s): 1632    Accepted Submission(s): 273

Special Judge

Problem Description
There are m
soda and today is their birthday. The 1-st
soda has prepared n
cakes with size 1,2,…,n.
Now 1-st
soda wants to divide the cakes into m
parts so that the total size of each part is equal.



Note that you cannot divide a whole cake into small pieces that is each cake must be complete in them
parts. Each cake must belong to exact one of m
parts.
 
Input
There are multiple test cases. The first line of input contains an integerT,
indicating the number of test cases. For each test case:



The first contains two integers n
and m(1≤n≤105,2≤m≤10),
the number of cakes and the number of soda.

It is guaranteed that the total number of soda in the input doesn’t exceed 1000000. The number of test cases in the input doesn’t exceed 1000.
 
Output
For each test case, output "YES" (without the quotes) if it is possible, otherwise output "NO" in the first line.



If it is possible, then output m
lines denoting the m
parts. The first number si
of i-th
line is the number of cakes in i-th
part. Then si
numbers follow denoting the size of cakes in i-th
part. If there are multiple solutions, print any of them.
 
Sample Input
4
1 2
5 3
5 2
9 3
 
Sample Output
NO
YES
1 5
2 1 4
2 2 3
NO
YES
3 1 5 9
3 2 6 7
3 3 4 8
 
Source
2015 Multi-University Training Contest 6





解题:

    比赛的时候以为是贪心,小数据试了几组发现,仅仅要当前最大的数没取,而且小于我如今剩余的值。那么就取并标记,实际上是错的。比方取了13,纵然还能取12,却不一定要取12,由于取了12后,会造成无法凑成那个平均数,因此如此贪心是不正确的。看赛后情况,预计绝大多数队伍都是水过的(貌似说当时Special Judge坏了),看是否正确跑下23 6这组数据大概就能知分晓了。

    正确解法(题解方法):先预处理出40之内全部能划分的情况。然后兴许的仅仅须要往前面处理好的情况上凑就好了。

比方先处理好了6 3的情况,计算54 3时:



     2 6 1

     2 5 2

     2 4 3



    18 6 1 7 12 13 18 19 24 25 30 31 36 37 42 43 48 49 54 

    18 5 2 8 11 14 17 20 23 26 29 32 35 38 41 44 47 50 53

    18 4 3 9 10 15 16 21 22 27 28 33 34 39 40 45 46 51 52



    红色部分是取的6 3处理好的结果,而后面蓝色部分则是两端对称构造的结果。

    感觉题解讲的并非非常清晰。可能会有人误觉得是一直用2m去减n,直至n小于40。那么便能够取前面已经预处理好的结果了,实际上还要满足(n-2m*x)要能被划分为y块。因此并非从后往前减,而是从前往后搜寻第一个合法的状态。至于题解中40是怎样产生的。渣渣实在是证明不了。但用了20去构造,发现是会不够用的,(測试中越界了)。

    构造过程事实上挺好理解的。就是高斯第1项和尾项的和等于第2项和倒数第2项的和,不断内移即可了。

总结:

    有时候不要太过想当然,上次bc的三角形数也是。贪心不要乱用,得有一定根据。

多校很喜欢考察构造题,上次一张图,再上次24算,发现某些状态数比較大的时候,就应该联想到构造。









疑点:      

    题解中的40,不知道是怎么蹦出来的,求大神证明!







代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#define LL long long
#define mod 1000000007
using namespace std;
//訪问和成功标记
bool status[45],sign;
//记录搜索路径
int path[45];
//平均值。cnt为当前第几组解
int ave,m,n,cnt;
//flag[x][y]表示x块蛋糕能不能划分为y部分
bool flag[45][12];
struct division
{
int a[45],sz;
}store[45][12][12];
//三维分别表示共多少,划分为几块。它的第几块是,以及内部存储各自是哪几块
//预处理。搜索
//pos为当前位置,left为剩余容量。p为路径中第几个数字
void dfs(int pos,int left,int p)
{
//当前状态下已经找到一种方案
if(sign)return;
//成功找到解
if(left==0)
{
//把路径中的值存入到数组中
for(int i=0;i<p;i++)
store[n][m][cnt].a[i]=path[i];
store[n][m][cnt].sz=p;
//成功标记
sign=true;
return;
}
for(int i=pos;i>=1;i--)
{
if(!status[i]&&left>=i)
{
//该点已訪问
status[i]=1;
path[p]=i;
dfs(i,left-i,p+1);
//避免把已经成功的点又一次置为0
if(sign)return;
status[i]=0;
}
}
}
//预处理
void prep()
{
memset(flag,0,sizeof(flag));
int tmp,total;
for(int i=1;i<=20;i++)
{
//tmp是依据n要小于等于平均值。计算出来的上界
tmp=(i+1)/2;
total=i*(i+1)/2;
for(int j=1;j<=tmp;j++)
{
//假设能够划分的话
if(total%j==0)
{
flag[i][j]=1;
memset(status,0,sizeof(status));
ave=total/j;
m=j;
n=i;
//循环找多组解
for(int k=0;k<j;k++)
{
cnt=k;
sign=false;
dfs(n,ave,0);
}
}
}
}
}
int main()
{
//预处理
prep();
int t,x,y,a,b,sz;
//读入
scanf("%d",&t);
LL total;
while(t--)
{
scanf("%d%d",&x,&y);
total=1LL*(1+x)*x/2;
ave=total/y;
//排除不能划分的情况
if((total%y)||(ave<x))
{
printf("NO\n");
continue;
}
//其余的都是可构造的
printf("YES\n");
m=y;
//注意m已经乘以2
m<<=1;
int g;
//找到第一个合法的状态
for(g=1;;g++)
{
//假设能够划分。并且后面多出的数刚好能够构造
if(flag[g][y]&&((x-g)%m)==0)
break;
}
//b为构造次数
b=(x-g)/m;
for(int i=0;i<y;i++)
{
sz=store[g][y][i].sz;
//总数量
printf("%d",sz+(b<<1));
//原有解
for(int k=0;k<sz;k++)
printf(" %d",store[g][y][i].a[k]);
//构造解
for(int k=0;k<b;k++)
printf(" %d %d",k*m+g+i+1,(k+1)*m+g-i);
printf("\n");
}
}
return 0;
}

HDU 5355 Cake (WA后AC代码,具体解析,构造题)的更多相关文章

  1. HDU 5355 Cake

    HDU 5355 Cake 更新后的代码: 今天又一次做这道题的时候想了非常多种思路 最后最终想出了自觉得完美的思路,结果却超时 真的是感觉自己没救了 最后加了记忆化搜索,AC了 好了先说下思路吧.不 ...

  2. 多校第六场 1003 hdu 5355 Cake(贪心)

    题目链接:(数据加强后wa了) hdu 5355 题目大意: 给出一个蛋糕.切成1~n大小的n块.问是否能在不继续分割的情况下拼凑出m等份. 题目分析: 首先我们是可以知道每份蛋糕的尺寸的,利用n*( ...

  3. 2015多校第6场 HDU 5355 Cake 贪心,暴力DFS

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5355 题意:给你n个尺寸大小分别为1,2,3,…,n的蛋糕,要求你分成m份,要求每份中所有蛋糕的大小之 ...

  4. HDU 1005 Number Sequence(AC代码)

    #include <stdio.h> #include <string.h> int main() { int a,b,n; int i; ]={}; f[]=; f[]=; ...

  5. HDU 1003 Max Sum(AC代码)

    #include <stdio.h> int main(){ int i,t,j,n,x; int start,end,temp,max,sum; scanf("%d" ...

  6. HDU 5355 Cake (构造 + 暴力)

    题意:给定 n,m,让你把 1 ~ n 分成 m 部分,而且每部分和是一样大的. 析:首先先判断不能分成的,第一种是 sum (1 ~ n 的和)不能被 m 整除,或者 sum / m < n, ...

  7. HDU 5355 Cake(2015多校第六场,搜索 + 剪枝)

    Cake Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Sub ...

  8. HDU 1001 Sum Problem(AC代码)

    #include <stdio.h> int main(){ int k,sum; while(scanf("%d",&k)!=EOF){ ==){ sum=( ...

  9. HDU 2222 Keywords Search(AC自己主动机模板题)

    题意:给出一个字符串和若干个模板,求出在文本串中出现的模板个数. 思路:由于有可能有反复的模板,trie树权值记录每一个模板出现的次数就可以. #include<cstdio> #incl ...

随机推荐

  1. JS-只能输入中文和英文

    <span style="font-family:KaiTi_GB2312;">转自:<a target=_blank href="http://www ...

  2. Intellij idea远程debug连接tomcat,实现单步调试

    转载:http://blog.csdn.net/boling_cavalry/article/details/73384036 web项目部署到tomcat上之后,有时需要打断点单步调试,如果用的是I ...

  3. Python&lt;1&gt;List

    list里的元素以逗号隔开,以[]包围,当中元素的类型随意 官方一点的说:list列表是一个随意类型的对象的位置相关的有序集合. 它没有固定的大小(1).通过对偏移量 (2)进行赋值以及其它各种列表的 ...

  4. 要做国外的app,使用到的分享和统计SDK推荐

    国内的就不说了,多如牛毛,常用的是友盟,极光,shareSDK等等. 国外的统计有: Flurry(https://developer.yahoo.com) google analytics(http ...

  5. 怎么运行Typescript

    依据官方示例: npm i -g typescript 示例:tsc *.ts 实例:tsc hello.ts 不过以上实现的太有限制了,如下实现可满足正常测试以及学习使用 package,json ...

  6. 创建你的第一个ionic+cordova应用(1)

    前面我们安装了前端的神器webstorm11,体验到了强大的开发体验,接着我们来安装ionic 必备: Node.js (npm安装工具) 百度下载 官网下载  注:如果官网新版不能安装请用百度下载0 ...

  7. Oracle 创建表空间、临时表空间、创建用户并指定表空间、授权,删除用户及表空间

    /* 说明:若已经存在相应的用户和表空间,则需要先删除相应的用户和表空间 然后再全部重新建立 */ --删除用户 drop user USERNAME cascade; --删除表空间 drop ta ...

  8. preloadjs实现网页资源预加载

    <!doctype html> <html lang="zh"> <head> <title>PreloadJS的基础使用</ ...

  9. hdu5399

    题意:给你m行个长度为 n的序列或者-1 -1代表这一行的序列不确定,然后让你找出有多少种情况满足对于每一个i 有f1(f2(⋯fm(i)))=i: 思路:分为三种情况:1,每行序列中有反复数输出0: ...

  10. python 用win32修改注册表,修改打开IE浏览器的配置

    打开注册表:win+r, regedit,注册表的管理是按照文件夹的形式的. 注册表总共有五项: HKEY_CLASSES_ROOT 是HKEY_LOCAL_MACHINE\Software的子项,保 ...