AHUICPC (Hard Version)

链接:https://ac.nowcoder.com/acm/contest/2720/G
来源:牛客网

本题的Easy Version与Hard Version的唯一区别是数据范围不同,因此可以通过Hard Version的代码可以直接通过Easy Version。
AHU ACM/ICPC实验室有着悠久而光荣的历史,学长学姐们拿过金牌,进过Google。无论经过多少人,我们都希望AHU ACM/ICPC实验室可以代表AHU的最高水平。正所谓与天壤而同久,共三光而永光。

现在给定一个整数n,表示AHU ACM/ICPC实验室经过了n≤109n \le 10^9n109代人。你需要让每个人得到一个字符串"AHUICPC",但由于n可能是一个很大的数,所以将字符串分给每一个人是不可行的。所以你现在要构造一个字符串,使得字符串中恰好有n个子序列为"AHUICPC",且字符串的长度不超过10510^5105。
对于字符串S,我们定义S[i1]S[i2]…S[in]S[i_1]S[i_2]\dots S[i_n]S[i1]S[i2]S[in]为S的长为n的子序列,其中i1<i2<⋯<ini_1<i_2<\dots < i_ni1<i2<<in。当且仅当i1=j1,i2=j2,…,in=jni_1=j_1,i_2=j_2,\dots ,i_n=j_ni1=j1,i2=j2,,in=jnS[i1]S[i2]…S[in]S[i_1]S[i_2]\dots S[i_n]S[i1]S[i2]S[in]和S[j1]S[j2]…S[jn]S[j_1]S[j_2]\dots S[j_n]S[j1]S[j2]S[jn]被视作同一个子序列。
比如对于字符串"abbc",其中存在两个子序列为"abc",存在一个子序列为"ac",但是不存在子序列"cb"。

 AC代码如下(其实一开始我也不会写,想到质因数分解上去了):

实际上这是数学题

讲解在后面

#include <iostream>
#include <cmath>
#include <string>
using namespace std;
int main()
{
    int n;
    string s_all;
    cin >> n;
    int a = sqrt(n);
    int b = n / a;
    int c = n - a * b;
    for (int i = 0; i < a; i++)
        s_all.append("A");
    for (int i = 0; i < b-1; i++)
        s_all.append("H");
    for (int i = 0; i < c; i++)
        s_all.append("A");
    s_all.append("HUICPC");
    cout << s_all << endl;
    return 0;
}

首先我们知道高中的时候我们学过一个叫均值不等式的东西

也就是说:
  如果有一个数n,我把它分成a*b=n

  显然可得(这次真的是显然可得了)

  当且仅当a=b时a+b的和最小

但是如果我们将

  n分成a*b*c三个数呢?

于是我们分下面几种情况讨论:

  1.c>1;

  2.c=1;

  将一个数分成三份显然比分成俩份大,所以也就说分的越多总和越大

为什么是显然:
  如果C>1;那么b*c肯定是大于分成俩份的b的,也就是a与b的差增大了,所以会小

  如果C=1;虽然b*c不变但是C本身还有一个1

因此我们可以得出一个规律:

  只要给的数不是质数(质数没有办法分解了)

  我都可以将它分成俩份,这样的和最小

是不是到这里就OK了呢?

Too young!

字符必须是整数

所以直接sqrt()不行

因此我们需要做的实际上是:

1.将n开平方得到a

2.将b=n/a这样尽量得到的是最接近平方的b

3.c=n-b*a 捡漏

有一个注意的地方是:

  b不能直接全部给"H",应该是b-1个,因为有一个”H“要给后面的c公用

猜你喜欢

转载自www.cnblogs.com/leader-one/p/12585434.html