• 【数学】codeforces C. Maximal GCD


    http://codeforces.com/contest/803/problem/C

    【题意】

    给定两个数n,k(1 ≤ n, k ≤ 10^10)

    要你输出k个数,满足以下条件:

    ①这k个数之和等于n

    ②严格递增

    ②输出的这k个数的最大公约数q尽可能大。

    【思路】

    因为是严格递增,所以sum[k]>=k(k+1)/2,而n<=1e10,所以k应该在1e5多一点。

    可以找出最大的满足n<=1e10的k,给定的k超出这个直接输出-1.

    然后接下来考虑怎么使最大公约数最大:

    因为q肯定也是n的约数,所以可以先把n的公约数都找出来,时间复杂度是O(sqrt(n)),从大到小排序后一次判断能不能满足q*(1+2+···+k)<=n就可以了。

    【注意】

    1. 判断q*(1+2+···+k)<=n不能写if(q*sum[k]<=n)

    会爆的,最大的q就是n本身,当n=1e10,k=1e5的时候,q*sum[k]就爆long long了,所以要写成

    1 if(sum[m]<=n/d[i])
    2     {
    3         return true;
    4     }
    5     return false;
    View Code

    2. 对于i*i==n的要特别判断

    3. 要特别考虑1 1的corner case.

    【Accepted】

      1 #include <iostream>
      2 #include <stdio.h>
      3 #include <cmath>
      4 #include <vector>
      5 #include <algorithm>
      6 #include <set>
      7 #include <map>
      8 #include <queue>
      9 #include <deque>
     10 #include <stack>
     11 #include <string>
     12 #include <bitset>
     13 #include <ctime>
     14 #include<algorithm>
     15 #include<cstring>
     16 using namespace std;
     17 typedef long long ll;
     18 ll n,m;
     19 const int maxn=1e6+2;
     20 ll sum[maxn];
     21 int cou;
     22 void Init()
     23 {
     24     memset(sum,0,sizeof(sum));
     25     for(int i=1;i<maxn;i++)
     26     {
     27         sum[i]=sum[i-1]+(ll)i;
     28         if(sum[i]>=10000000000)
     29         {
     30             cou=i;
     31             break;    
     32         }
     33     }
     34 }
     35 ll d[1000000];
     36 bool cmp(ll a,ll b)
     37 {
     38     return a>b;
     39 }
     40 
     41 bool judge(int i)
     42 {
     43     if(sum[m]<=n/d[i])
     44     {
     45         return true;
     46     }
     47     return false;
     48 }
     49 void Print(int i)
     50 {
     51     for(int k=1;k<=m-1;k++)
     52     {
     53         cout<<d[i]*(ll)k<<" ";
     54     }
     55     cout<<n-d[i]*sum[m-1]<<endl; 
     56 }
     57 int main()
     58 {
     59     Init();
     60     cin>>n>>m;
     61     if(m>=cou)
     62     {
     63         printf("-1
    ");
     64         return 0;
     65     }
     66     if(sum[m]>n)
     67     {
     68         printf("-1
    ");
     69         return 0;
     70     }
     71     int cnt=0;
     72     ll index=0;
     73     for(int i=1;(ll)i*(ll)i<n;i++)
     74     {
     75         if(n%(ll)i==0)
     76         {
     77             d[cnt++]=(ll)i;
     78             d[cnt++]=n/(ll)i;
     79         }
     80         index=(ll)i;
     81     }
     82     index++;
     83     if(index*index==n)
     84     {
     85         d[cnt++]=index;
     86     }
     87     sort(d,d+cnt,cmp);
     88     int flag=0;
     89     for(int i=0;i<cnt;i++)
     90     {
     91         if(judge(i))
     92         {
     93             flag=1;
     94             Print(i);
     95             break;
     96         }    
     97     }
     98     if(flag==0)
     99     {
    100         printf("-1
    ");
    101     }
    102     return 0;
    103 }
    注意爆ll,注意corner case
  • 相关阅读:
    2017已过半,这半年,你累吗?
    2017已过半,这半年,你累吗?
    2017已过半,这半年,你累吗?
    程序员的一个好习惯,你有几个?
    程序员的一个好习惯,你有几个?
    程序员的一个好习惯,你有几个?
    深拷贝与浅拷贝
    understanding android build layer · Dylan
    Markdown语法
    npm参考手册
  • 原文地址:https://www.cnblogs.com/itcsl/p/6986106.html
Copyright © 2020-2023  润新知