hdu4982 暴搜+剪枝(k个数和是n,k-1个数的和是平方数)
2024-10-19 07:54:33
题意:
给你两个数n,k问你是否怎在这样一个序列:
(1)这个序列有k个正整数,且不重复.
(2)这k个数的和是n.
(3)其中有k-1个数的和是一个平方数.
思路:
直接暴搜,一开始剪枝没写好,TLE了几次。这个题目我们可以枚举所有小于n的平方数,然后搜索去构造,用k-1个数构造出来当前的这个平方数,同时自己还写了几个小枝.
a:求了一个枚举的下界,那就是1+2+3+...+ k-1,上界是n。
b:对于每一次,枚举深搜的时候的最大数 = 当前枚举数 i -(1+2+..+k-2)
c:深搜的时候,因为枚举是越来越大的,那么如果当前的和sum,剩余的枚举个数(k-1-s),剩下的全是连续的,那么剩下的数的平均数是当前数now加上(k-1-s)/ 2,如果当前的和加上剩下的数的最小和大于当前枚举的平方数,那么当前状态失败,表示是
if(sum + (k - 1 - s) * (now + (k - 1 - s) / 2) > nowsum) return.
#include<stdio.h>
#include<string.h>
int mark[222222];
int n ,k ,ok ,nowsum ,max ,nowmk; void DFS(int now ,int s ,int sum)
{
if(s == k - 1)
{
if(sum == nowsum) ok = 1;
return;
}
if(sum + (k - 1 - s) * (now + (k - 1 - s) / 2) > nowsum) return;
for(int i = now + 1 ;i <= max && !ok;i ++)
if(i != nowmk) DFS(i ,s + 1 ,sum + i);
} int main ()
{
memset(mark ,0 ,sizeof(mark));
for(int i = 1 ;1 ;i ++)
{
int tmp = i * i;
if(tmp > 200000) break;
mark[tmp] = 1;
}
while(~scanf("%d %d" ,&n ,&k))
{
int min = 0;
for(int i = 1 ;i <= k - 1 ;i ++)
min += i;
ok = 0;
for(int i = n - 1 ;i >= min && !ok;i --)
{
if(!mark[i]) continue;
nowmk = n - i;
max = 0;
for(int j = 1 ;j < k - 1 ;j ++)
max += j;
max = i - max;
nowsum = i;
DFS(0 ,0 ,0);
}
if(ok) printf("YES\n");
else printf("NO\n");
}
return 0;
}
最新文章
- js中的this,call及apply
- libevent源码分析:eventop
- 2016HUAS_ACM暑假集训4A - 递推
- C#制作验证码
- Maven-003-私人定制 maven archetype
- Smartforms常见问题
- Linux下把Mysql和Apache加入到系统服务里
- 如何使用javadoc
- UVA 10970 第一次比赛 D题 (后面才补的)
- WPF简单布局 浅尝辄止
- POJ2531——Network Saboteur(随机化算法水一发)
- redux-applyMiddleware实现理解+自定义中间件
- Git 版本控制工具使用介绍------Windows系统下使用
- URI、URL和URN之间的区别与联系
- Oracle中merge into的使用 (转)
- javascipt : filter
- ionic3-ng4学习见闻--(多环境方案)
- python3下爬取网页上的图片的爬虫程序
- 从零开始学安全(二十四)●用Nmap发现主机
- poj2449 第k短路