zoukankan      html  css  js  c++  java
  • HDU 5439 Aggregated Counting

    题目大意:

    由1开始不断往数组中添加数

    就是按照当前所在位置所在的数表示的个数添加这个数目的数

    1 2 2 3 3 后面因为要填4,而4号位置为3,说明之后要填3个4

    问题就是给定一个n,找到n出现的最后位置p,再找p出现的最后位置即可

    这里可以考虑先找到g[i]表示 i 连续出现了多少次

    这里想一下的话,因为g[i] 相当于 i 位置出现的数

    所以g[i]也满足这个序列

    令f[i] 表示 i 出现的最后位置,也就是1~i的总个数

    后面去计算g[i]的时候就可以考虑的是找到第 i 个位置在那个f[]的区间内  , 如果f[k-1]< i <= f[k]

    那么说明此时 g[i] = k

    那么就可以logn的复杂度计算g[n]了

    要计算最后的答案,要考虑的是,给定的n,找到最后出现的p,中间长度 p = g[1]+g[2]....+g[p]

    然后再找对应的ans ,那么每次增加的g[i],就会让整个序列 的长度增加 i*g[i]

     i*g[i] 可以理解为的是,长度为i的数量有g[i]个, 所以总长度是i*g[i]

    所以ans = sigma(i*g[i]) i<=n

    那么对于n <= 1e9

    那么大致计算一下会发现f[500000]>1e9

    所以g[n]<500000只要暴力求出前500000的g[] , f[]

    那么答案计算前,先找到g[n]是多少

    g[n]= lower_bound(f+1 , f+N+1 , n)-f

    然后说明[1 , g[n]-1]这一段区间内的所有长度都被用到了

    所以之前预处理这个长度的前缀和 sum[]

    对于每一个长度 i ,他出现的次数都是 f[i]-f[i-1]

    sigma(n*g[n]) f[i-1]<n<=f[i]  -> g[n] = i

    那么答案就是 i*等差数列了,记得取模(⊙o⊙)哦

    然后(g[n]-1 , g[n]]这一段只要枚举 (g[n]-1 , n] 就可以了

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <vector>
     5 #include <queue>
     6 using namespace std;
     7 #define M 26
     8 #define N 500000
     9 #define ull unsigned long long
    10 #define ll long long
    11 const int MOD = 1000000007;
    12 int f[N+2] , g[N+2] , cnt[N+2];
    13 ll sum[N+2];
    14 
    15 int Hash(int v)
    16 {
    17     return lower_bound(f+1 , f+N+1 , v)-f;
    18 }
    19 
    20 void init()
    21 {
    22     g[1] = 1 , f[1] = 1;
    23     g[2] = 2 , f[2] = 3;
    24     for(int i=3 ; i<=N ; i++){
    25         g[i] = lower_bound(f+1 , f+i , i)-f;
    26         f[i] = f[i-1]+g[i];
    27     }
    28 //    for(int i=1 ;i<=100 ; i++)
    29 //        cout<<i<<" "<<g[i]<<" "<<f[i]<<endl;
    30 //    cout<<f[N]<<endl;
    31 
    32     sum[1] = 1;
    33     for(int i=2 ; i<=N ; i++){
    34         sum[i] = sum[i-1]+(ll)(f[i-1]+1+f[i])*(f[i]-f[i-1])/2 % MOD * (ll)i % MOD;
    35       //  if(i<=10) cout<<"sum: "<<i<<" "<<sum[i]<<endl;
    36     }
    37 }
    38 int main() {
    39 //    freopen("a.in" , "r" , stdin);
    40 //    freopen("out.txt" , "w" , stdout);
    41 
    42     init();
    43     int T , n;
    44     scanf("%d" , &T);
    45     while(T--){
    46         scanf("%d" , &n);
    47         int pos = Hash(n);
    48         ll ret = sum[pos-1];
    49         for(int i=f[pos-1]+1 ; i<=n ; i++) //这个区间每个长度都为pos
    50         {
    51             ret = (ret+(ll)i*pos)%MOD;
    52         }
    53         printf("%I64d
    " , ret);
    54     }
    55     return 0;
    56 }
  • 相关阅读:
    Springboot整合Dubbo
    网站appache的ab命令压力测试性能
    静态页面框架
    CSS布局设计
    弹性盒子的总结
    弹性盒子
    应用媒介查询制作响应式导航栏
    响应式的设计需要遵守的4个原则和媒介查询语句
    media type的类型汇总
    background-orgin属性
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4805973.html
Copyright © 2011-2022 走看看