1. 程式人生 > >Maximal GCD CodeForces - 803C (數論+思維優化)

Maximal GCD CodeForces - 803C (數論+思維優化)

C. Maximal GCD time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output

You are given positive integer number n. You should create such strictly increasing sequence of k positive numbers a1, a2, ..., ak, that their sum is equal to n and greatest common divisor is maximal.

Greatest common divisor of sequence is maximum of such numbers that every element of sequence is divisible by them.

If there is no possible sequence then output -1.

Input

The first line consists of two numbers n and k (1 ≤ n, k ≤ 1010).

Output

If the answer exists then output k numbers — resulting sequence. Otherwise output -1. If there are multiple answers, print any of them.

Examples input Copy
6 3
output Copy
1 2 3
input Copy
8 2
output Copy
2 6
input Copy
5 3
output Copy
-1

題目連結:https://vjudge.net/problem/CodeForces-803C#author=0
一題目大意:給你一個N和K,讓你輸出K個數,使其K個數的和為N,並且這K個數是嚴格遞增的,同時要求這K個數的gcd儘可能的大。
思路:
首先我們要用思維優化一下:
通過觀察資料範圍,我們可以看到K最值可以取到1e10,那麼題目又要輸出K個數,光輸出K個數的時間複雜度就是O(K)了,題目要求1000ms,肯定會TLE。
那麼我們應該知道肯定當K大於一個數值的時候,就不存在答案輸出-1了。
由於要求這K個數是嚴格遞增的,那麼不難想到,當gcd最小為1的時候,也是1,2,3,5,6,,..,k。
那麼這K個數的總和就是(K*(1+K))/2,(等差數列的公式),即如果這個數大於N的時候,是無解的輸出-1,那麼根據N最大可以取到1e10,我們可以算出K的最值應該是141420,
當K>141420的時候,直接輸出-1表示無解。原因上邊已經論述,這時候的總和是大於1e10的,即大於N的值。
然後我們進行有解的情況。
首先要使K個數和為N,並且GCD儘可能的大, 我們應該可以得知這樣一個資訊,這個GCD一定是N的一個因子(因為K個數都可以被gcd整除,那麼他的和也一定被gcd整除)
這樣我們首先O(sqrt(N))的時間裡求出N的所有因子,然後從大到小排序(貪心的思想,因為題目要求gcd儘量大)。
並且只有當n/gcd >= ((K*(1+K))/2) 的時候,才會構造出以gcd為a1值公差為gcd的等差數列。

然後我們就只需要用程式碼實現出這個過程就好了。(本文原文出處:https://www.cnblogs.com/qieqiemin/
我的AC程式碼:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb std::ios::sync_with_stdio(false)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define gg(x) getInt(&x)
using namespace std;
typedef long long ll;
inline void getInt(int* p);
const int maxn=1000010;
const int inf=0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
ll n,k;
vector<ll> foc;
int main()
{
//    gbtb;
//    cin>>n>>k;
    scanf("%lld %lld",&n,&k);
    ll sum=(k*(1ll+k)/2ll);
    if(sum>n||k>=141421ll)
    {
//        cout<<-1<<'\n';
        printf("-1\n");
    }else
    {
        if(k==1ll)
        {
//            cout<<n<<'\n';
            printf("%lld\n",n);
        }else
        {
            int num;
            ll js=sqrt(n);
            for(ll i=1ll;i<=js;i++)
            {
                if(n%i==0)
                {
                    foc.push_back(i);
                    if(i*i!=n)
                    {
                        foc.push_back(n/i);
                    }
                }
            }
            sort(foc.begin(),foc.end());
            reverse(foc.begin(),foc.end());
            ll gcd;
            num=foc.size();
            for(int j=0;j<num;j++)
            {
                ll i=foc[j];
                if(n%i==0)
                {
                    ll cnt=n/i;
                    if(cnt>=sum)
                    {
                        gcd=i;
                        break;
                    }
                }
            }
            ll now=gcd;
            ll he=0ll;
            for(ll i=1ll;i<=k-1;i++)
            {
                he+=now;
                printf("%lld ",now);
                now+=gcd;
            }
            printf("%lld ",n-he);
        }
    }
    return 0;
}

inline void getInt(int* p) {
    char ch;
    do {
        ch = getchar();
    } while (ch == ' ' || ch == '\n');
    if (ch == '-') {
        *p = -(getchar() - '0');
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 - ch + '0';
        }
    }
    else {
        *p = ch - '0';
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 + ch - '0';
        }
    }
}
View Code