[hdu5439 Aggregated Counting]公式化简,预处理

题意:按下列规则生成一组序列,令f(n)为n这个数在序列中出现的最后一个位置,求f(f(n))的值。

1. First, write down 1, 2 on a paper.
2. The 2nd number is 2, write down 2 2’s (including the one originally on the paper). The paper thus has 1, 2, 2 written on it.
3. The 3rd number is 2, write down 2 3’s. 1, 2, 2, 3, 3 is now shown on the paper.
4. The 4th number is 3, write down 3 4’s. 1, 2, 2, 3, 3, 4, 4, 4 is now shown on the paper.
5. The procedure continues indefinitely as you can imagine. 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 6, . . . .

思路:令原序列为a,根据定义和序列的生成规则可以推出:

  • f(n)等于a的前n项和
  • f(n)是n这个数在a中出现的最后一个位置

f(f(n))的含义为:a的前m项和,m为n在a中最后出现的位置。所以f(f(n))的计算式可以写成:

f(f(n))=1 + (2+3)*2 + (4+5)*3 + (6+7+8)*4 + ... + (...+n)*t

t是远小于n的,大概为几十万的样子,剩下的就不多说了。。。

#pragma comment(linker, "/STACK:10240000")
#include <bits/stdc++.h>
using namespace std;

#define X                   first
#define Y                   second
#define pb                  push_back
#define mp                  make_pair
#define all(a)              (a).begin(), (a).end()
#define fillchar(a, x)      memset(a, x, sizeof(a))

typedef long long ll;
typedef pair<int, int> pii;

namespace Debug {
void print(){cout<<endl;}template<typename T>
void print(const T t){cout<<t<<endl;}template<typename F,typename...R>
void print(const F f,const R...r){cout<<f<<" ";print(r...);}template<typename T>
void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}
}
template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);}
template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);}
/* -------------------------------------------------------------------------------- */

const int maxn = 1e9 + 7;
const int mod = maxn;

int seq[600000] = {0, 1, 2, 2};
ll sum[600000] = {0, 1, 3, 5}, ans[600000];
int total = 3;
void init() {
    for (int i = 3; ; i ++) {
        for (int j = 0; j < seq[i]; j ++) {
            seq[++ total] = i;
            sum[total] = sum[total - 1] + seq[total];
        }
        if (sum[total] > maxn) break;
    }
    ans[1] = 1;
    for (int i = 2; i < total; i ++) {
        ans[i] = (ans[i - 1] + (sum[i] + sum[i] - seq[i] + 1) * seq[i] / 2 % mod * i) % mod;
    }
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGE
    int T, n;
    init();
    cin >> T;
    while (T --) {
        cin >> n;
        int p = upper_bound(sum + 1, sum + total, n) - sum - 1;
        cout << (ans[p] + (sum[p] + 1 + n) * (n - sum[p]) / 2 % mod * (p + 1)) % mod << endl;
    }
}
原文地址:https://www.cnblogs.com/jklongint/p/4809030.html