CodeForces 803C Maximal GCD 思维
题意:给出 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; }