hdu 5646DZY Loves Partition(构造)
DZY Loves Partition
Accepts: 154
Submissions: 843
Time Limit: 4000/2000 MS (Java/Others)
Memory Limit: 262144/262144 K (Java/Others)
问题描述
DZY喜欢拆分数字。他想知道能否把n拆成恰好k个不重复的正整数之和。 思考了一会儿之后他发现这个题太简单,于是他想要最大化这k个正整数的乘积。你能帮帮他吗? 由于答案可能很大,请模109+7输出。
输入描述
第一行t,表示有t组数据。 接下来t组数据。每组数据包含一行两个正整数n,k。 (1≤t≤50,2≤n,k≤109)
输出描述
对于每个数据,如果不存在拆分方案,输出−1;否则输出最大乘积模109+7之后的值。
输入样例
4 3 4 3 2 9 3 666666 2
输出样例
-1 2 24 110888111
Hint
第一组数据没有合法拆分方案。 第二组数据方案为3=1+2,答案为1×2=2 第三组数据方案为9=2+3+4,答案为2×3×4=24。注意9=3+3+3是不合法的拆分方案,因为其中包含了重复数字。 第四组数据方案为666666=333332+333334,答案为333332×333334=111110888888。注意要对109+7取模后输出,即110888111。
思路:
首先试了一下: 9拆成3个可以拆分成2+3+4 or 1+3+5,但是很明显前一个的积要大,而且多试了几个都是如此。所以考虑拆成一段连续的数,它们积较大。但是n拆成k个连续数的和后可能有剩余,于是可以考虑吧它们添加到这k个数上面。很明显从前面添加会有重复,所以如果剩余了m,则在倒数m个数上面均加上1.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | #include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <map> #include <algorithm> using namespace std; typedef long long ll; #define LL(x) (x<<1) #define RR(x) (x<<1|1) const ll MOD = 1e9 + 7; const int maxn = 305; int main() { int T; ll n,k; ll t; scanf ( "%d" ,&T); while (T--) { scanf ( "%I64d%I64d" ,&n,&k); if (k%2) t = (ll)(k+1)/2*k; else t = (ll)k/2*(k+1); if (t > n) { printf ( "-1\n" ); continue ; } else { ll po = n-t; ll bei = po/k; ll els = po%k; //cout << bei <<" "<<els<<endl; ll ans = 1; for (ll i = k; i >= 1; i--) { ll cur = i+bei; if (els) { cur++; els --; } ans = (ll)ans*cur%MOD; } printf ( "%I64d\n" ,ans); } } return 0; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步