博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
hdu4982 Goffi and Squary Partition (DFS解法)
阅读量:6858 次
发布时间:2019-06-26

本文共 4863 字,大约阅读时间需要 16 分钟。

 B

Goffi and Squary Partition

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 308    Accepted Submission(s): 106

Problem Description
Recently, Goffi is interested in squary partition of integers.
A set \(X\) of \(k\) distinct positive integers is called squary partition of \(n\) if and only if it satisfies the following conditions: [ol]
  • the sum of \(k\) positive integers is equal to \(n\)
  • one of the subsets of \(X\) containing \(k - 1\) numbers sums up to a square of integer.[/ol] For example, a set {
    1, 5, 6, 10} is a squary partition of 22 because 1 + 5 + 6 + 10 = 22 and 1 + 5 + 10 = 16 = 4 × 4.
    Goffi wants to know, for some integers \(n\) and \(k\), whether there exists a squary partition of \(n\) to \(k\) distinct positive integers.
 
Input
Input contains multiple test cases (less than 10000). For each test case, there's one line containing two integers \(n\) and \(k\) (\(2 \le n \le 200000, 2 \le k \le 30\)).
 
Output
For each case, if there exists a squary partition of \(n\) to \(k\) distinct positive integers, output "YES" in a line. Otherwise, output "NO".
 
Sample Input
2 2 4 2 22 4
 
Sample Output
NO YES YES
 
Source
 
Recommend
heyang   |   We have carefully selected several similar problems for you: 

题意:给出n和k,求k个不同的正整数,使其中k-1个数能组成平方数,k个数的和为n。有解输出YES,无解输出NO。

题解:从大到小枚举小于n的平方数,剪枝搜索是否有解。

先判一下是不是1~k这最小的k个数加起来都超过n,这种情况肯定不可能,真去搜一遍的话太费时间了,还是特判掉比较好。

if((1+k)*k/2>n)return 0;

枚举平方数,进入搜索:

1     t=sqrt(1.0*n);2     if(t*t==n)t--;3     for(i=t; i>=1; i--) {4         int lost=i*i;5         Remove(n-lost);6         if(dfs(lost,2,R[n]))return 1;7         Resume(n-lost);8     }

↑(这个在函数里,return 1是有解。)

这题每个数只用一次,所以枚举一个数,下个数可以从这个数+1开始枚举。我使用了DancingLinks那种超碉的结构,不过其实只用一个used[]就好了……

比赛的时候这样就能过了,因为n大的时候很容易就找到解,dfs不耗多长时间。不过今天一看居然加强了数据,会TLE,所以我们来加个剪枝:

当枚举第x个数时,剩下(k-x+1)个数,枚举i为当前的数,如果i+ (i+1)+(i+2)+...+(i+k-x)这以i开头的最小的k-x+1个数都大于剩下的数了,就不用继续枚举i了。

等差数列求和,(i + i+(k-x))*(k-x+1)/2 > lost,搞一搞可以把 i 移出来,得到i的最大值。

DFS代码:

1 bool dfs(const int &lost,const int &x,const int &now) { 2     if(x>k) { 3         if(lost==0) 4             return 1; 5         else return 0; 6     } 7     if(lost<=0)return 0; 8     if(x!=k) { 9         int maxi=((lost+lost)/(k-x+1)-(k-x))/2;///剩下的大于i的最小的(k-x+1)个数加起来超的话就跳10         maxi=min(maxi,n-1);11         for(int i=now; i<=maxi; i=R[i]) {12             Remove(i);13             if(dfs(lost-i,x+1,R[i]))return 1;14             Resume(i);15         }16     } else {17         if(L[R[lost]]==lost) {18             Remove(lost);19             if(dfs(0,x+1,R[lost]))return 1;20             Resume(lost);21         }22     }23     return 0;24 }

 

(这题的正解好像是各种情况都考虑一下,直接几个if就判出来了……我是不太懂)(还有官方题解说平方数只用枚举最大的那个就行,可是8 2这组数据,最大的平方数是4,然后就逗乐啊……虽然好像只有这一组数据有问题)

 

全代码:

1 //#pragma comment(linker, "/STACK:102400000,102400000")  2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 using namespace std; 13 #define ll long long 14 #define usll unsigned ll 15 #define mz(array) memset(array, 0, sizeof(array)) 16 #define minf(array) memset(array, 0x3f, sizeof(array)) 17 #define REP(i,n) for(i=0;i<(n);i++) 18 #define FOR(i,x,n) for(i=(x);i<=(n);i++) 19 #define RD(x) scanf("%d",&x) 20 #define RD2(x,y) scanf("%d%d",&x,&y) 21 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z) 22 #define WN(x) prllf("%d\n",x); 23 #define RE freopen("D.in","r",stdin) 24 #define WE freopen("1biao.out","w",stdout) 25 #define mp make_pair 26 #define pb push_back 27 28 const int maxn=222222; 29 int L[maxn],R[maxn]; 30 inline void Remove(int x) { 31 L[R[x]]=L[x]; 32 R[L[x]]=R[x]; 33 } 34 35 inline void Resume(int x) { 36 L[R[x]]=x; 37 R[L[x]]=x; 38 } 39 40 int n,k; 41 42 bool dfs(const int &lost,const int &x,const int &now) { 43 if(x>k) { 44 if(lost==0) 45 return 1; 46 else return 0; 47 } 48 if(lost<=0)return 0; 49 if(x!=k) { 50 int maxi=((lost+lost)/(k-x+1)-(k-x))/2;///剩下的大于i的最小的(k-x+1)个数加起来超的话就跳 51 maxi=min(maxi,n-1); 52 for(int i=now; i<=maxi; i=R[i]) { 53 Remove(i); 54 if(dfs(lost-i,x+1,R[i]))return 1; 55 Resume(i); 56 } 57 } else { 58 if(L[R[lost]]==lost) { 59 Remove(lost); 60 if(dfs(0,x+1,R[lost]))return 1; 61 Resume(lost); 62 } 63 } 64 return 0; 65 } 66 67 bool farm(int _n,int _k) { 68 int t; 69 int i,j; 70 n=_n; 71 k=_k; 72 if((1+k)*k/2>n)return 0; 73 for(i=2; i<=n; i++) { 74 L[i]=i-1; 75 R[i-1]=i; 76 } 77 L[1]=n; 78 R[n]=1; 79 t=sqrt(1.0*n); 80 if(t*t==n)t--; 81 for(i=t; i>=1; i--) { 82 int lost=i*i; 83 Remove(n-lost); 84 if(dfs(lost,2,R[n]))return 1; 85 Resume(n-lost); 86 } 87 return 0; 88 } 89 90 int main() { 91 int i; 92 int n,k; 93 while(scanf("%d%d",&n,&k)!=EOF) { 94 if(farm(n,k))printf("YES\n"); 95 else printf("NO\n"); 96 // for(i=0;i
View Code

 

转载于:https://www.cnblogs.com/yuiffy/p/3934478.html

你可能感兴趣的文章
轻松应对双十一零点的DNS流量洪峰
查看>>
有了“全程管家” 还担心P2O吗?
查看>>
NetApp CMO:如何释放数据的潜能成为企业核心诉求
查看>>
避免勒索软件威胁的十大技巧
查看>>
中国人工智能学会通讯——人工智能将引发未来网络产业变革
查看>>
向奇汉:服务企业互联网化 打造社会化商业平台
查看>>
SaaS在线管进销存 安全不是问题
查看>>
《网络空间欺骗:构筑欺骗防御的科学基石》一1.6.1 目的:合法与被控制的凭证...
查看>>
IDC:2016年上半年宏杉科技同比增长47.3%
查看>>
嵌入式数据中心有望胜过超大规模数据中心?
查看>>
《中国人工智能学会通讯》——7.22 知识图谱应用的基本技术
查看>>
CloudCC:如何用CRM打造客户关系管理新模式
查看>>
安全走向开放 建安全架构协同互联生态体系
查看>>
Linux新手最容易跳进哪几个坑?
查看>>
Linux 平台下 Python 脚本编程入门(二)
查看>>
IBM罗睿兰:认知计算将带领医疗走向黄金时代
查看>>
移动医疗怎么才能跟护士愉快地玩耍?
查看>>
大数据流量:数据中心发展的瓶颈
查看>>
网络虚拟化之FlowVisor:网络虚拟层(上)
查看>>
使用 rsync 来备份 Linux 系统
查看>>