题目传送门
题意:
给你两个正整数n和k。让你构造一个长度为k的严格递增序列,使这个序列gcd最大。且这个序列的和等于n。
如果不能构造,输出-1。
数据范围: 。
题解:
如果 ,无解。其他情况都有解。
然后你可以二分算出 的最大的 。或者你开根号算,我觉得二分方便用的二分。
然后在 中找满足 的最大 ,即为最大 。
然后这个序列变成了 。
但是序列和可能小于n,补在最后一项即可。
感受:
先是做一个2000分的题,不会,看题解也看不懂。
然后换这个题做,只有一个感觉,这题大写的枚举为什么会有2000分。。。。。
代码:
#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
ll solve(ll n)
{
ll l = 1 , r = 1e6 , ans = 1 ;
while(l <= r)
{
ll mid = (l + r) / 2 ;
if(mid * (mid + 1) / 2 <= n)
ans = mid , l = mid + 1 ;
else
r = mid - 1 ;
}
return ans ;
}
ll Find(ll n , ll k)
{
ll d = 1 , s = k * (k + 1) / 2 ;
ll m = n / s ;
for(ll i = 1 ; i * i <= n ; i ++)
{
if(n % i != 0) continue ;
if(i <= m) d = max(d , i) ;
if(n / i <= m) d = max(d , n / i) ;
}
return d ;
}
void print(ll n , ll k , ll d)
{
ll ans = 0 ;
for(int i = 1 ; i <= k ; i ++)
{
if(i == k){printf("%lld\n" , n) ; return ;}
ans += d , n -= ans ;
printf("%lld " , ans) ;
}
}
int main()
{
ll n , k ;
scanf("%lld%lld" , &n , &k) ;
ll Max = solve(n) ;
if(k > Max)
printf("-1\n") ;
else
{
ll d = Find(n , k) ;
print(n , k , d) ;
}
return 0 ;
}