codeforce 803C Maximal GCD(构造)

题意:对于给定n,k 求一个有k个数的上升序列,序列的和为n。且序列的最大公约数最大。

首先1s的时间 n k的数量级都是1e10 ,因此肯定要降低复杂度。
假设存在一个这样的序列,设序列的最大公约数为gcd,那么这个序列一定可以为

1gcd,2gcd,3gcd....(k1)gcd,kgcd

这个序列和的最大值为gcdk(k+1)2
且这个序列满足
gcdk(k+1)2n

n最大取1e10,可以考虑gcd=1的情况,用(k+1)2代替k(k+1)此时k取得最大值21051
所以,当k比最大值大的时候就无法满足条件,输出-1;

如果要构造一个存在最大的最大公约数的序列,可以利用n的因子进行构造,用数组存取n的因子,从大向小遍历。

当某个因子d能够满足dk(k+1)2n时,说明这个因子可以用来进行构造,前k-1个因子直接按1d,2d...(k1)d构造即可,对于第k个数,因为k*d可能不能正好满足k个数相加等于n,因此用n-(前面k-1个数的和)构造。

证明一下第k个数可以这样构造:
因为前k-1个数的和为dk(k1)2
所以第k个数为ndk(k1)2
因为d是n的因子,所以第k个数是一个整数。
对于第k个数除以d的结果ndk(k1)2,当第k个数恰好为k*d时,这个结果也是k。

注意的一点是在判断 因子是否满足条件dk(k+1)2n时,左边的结果可能会爆longlong。。可以强制转换成long double进行比较。。

#1include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 1E6;
ll gcd[N];
int main(){
    ll n,k;
    while(~scanf("%lld %lld",&n,&k)){
        if(k>=1e5*1.414-1) puts("-1");
        else{
            int cnt=0;
            for(int i=1;i<=sqrt(n);i++){
                if(n%i==0){
                    gcd[cnt]=i;
                    cnt++;  
                    gcd[cnt]=n/i;
                    cnt++;
                }
            }   
            sort(gcd,gcd+cnt);
            ll sum=0;
            int flag=1;
            for(int i=cnt-1;i>=0;i--){
                if((long double)gcd[i]*(long double)k*(long double)(k+1)/2<=(long double)n){

                    flag=0;
                    for(int j=1;j<k;j++){
                        printf("%lld ",j*gcd[i]);
                        sum+=j*gcd[i];
                    }
                    printf("%lld\n",n-sum);
                    break;
                }
            }
            if(flag) puts("-1");

        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值