CodeForces 803C Maximal GCD 思维

CodeForces 803C

题意:给出 n , k,要构造一个长度为 k 的严格递增序列,且这 k 个数的和为 n 。 问这 k 个数可能的最小 gcd 。

tags:先想到  a1+a2+....+ak=n, 则 ( b1+b2+.....+bk ) * gcd = n 。这样就可枚举或者二分 gcd,然后 check  ,只要 (1+2+....+k)=k*(k+1)/2 小于或等于 n/gcd 即可。

有个坑, k 是1e10, k*(k+1) 会爆 long long ,所以一开始特判一下, k 太大就肯定不可能。

// 803C
#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
const int N = 2000005;

ll  n, k, d[N], a[N];
int cnt;
bool check(int gcd)
{
    if(k*(k+1)/2 <= n/gcd) return true;
    return false;
}
int main()
{
    scanf("%lld%lld", &n, &k);
    if(k>5e5) return 0*printf("-1\n");
    for(int i=1; i<=sqrt(n); ++i)
        if(n%i==0)
    {
        d[++cnt]=i;
        if(n/i != i) d[++cnt]=n/i;
    }
    sort(d+1, d+1+cnt);
    int l=1, r=cnt, ans=-1, mid;
    while(l<=r)
    {
        mid = l+r>>1;
        if(check(d[mid])) ans=mid, l=mid+1;
        else r=mid-1;
    }
    if(ans==-1) return 0*printf("-1\n");
    rep(i,1,k)
    {
        a[i] = 1LL*i*d[ans];
        n -= a[i];
    }
    a[k] += n;
    rep(i,1,k) printf("%lld ", a[i]);

    return 0;
}
posted @ 2017-10-09 13:34  v9fly  阅读(147)  评论(0编辑  收藏  举报