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\n" , ret);
54     }
55     return 0;
56 }
时间: 2024-10-21 22:51:25

HDU 5439 Aggregated Counting的相关文章

Hdu 5439 Aggregated Counting (2015长春网络赛 ACM/ICPC Asia Regional Changchun Online 找规律)

题目链接: Hdu 5439 Aggregated Counting 题目描述: 刚开始给一个1,序列a是由a[i]个i组成,最后1就变成了1,2,2,3,3,4,4,4,5,5,5.......,最后问a[i]==n(i最大)时候,i最后一次出现的下标是多少? 解题思路: 问题可以转化为求a[i] == n (i最大),数列前i项的和为多少. index: 1 2 3 4 5 6 7 8 9 10 a:        1 2 2 3 3 4 4 4 5 5 可以观察出:ans[1] = 1,

hdu 3518 Boring counting(后缀数组)

Boring counting                                                                       Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Problem Description 035 now faced a tough problem,his english teacher gives him

HDU 1718 Rank counting sort解法

本题是利用counting sort的思想去解题. 注意本题,好像利用直接排序,然后查找rank是会直接被判WA的,奇怪的判断系统. 因为分数值的范围是0到100,非常小,而student 号码又非常大,故此天然的需要利用counting sort的情况. #include <stdio.h> #include <string.h> const int MAX_N = 101; int arr[MAX_N]; int main() { int Jackson, JackScore,

Aggregated Counting(找规律 + 预处理)

Aggregated Counting 转 : https://blog.csdn.net/cq_phqg/article/details/48417111 题解: 可以令n=1+2+2+3+3+......+ i    这个序列的长度为p 那么a[n]=1*1+2*2+3*2+...... + p*i 那么不难发现a[a[n]] = 1*1 + (2+3)*2 + (4+5)*3 + (6+7+8)*4 + ... + (pre+1 + pre+2 + ... + pre+b[p] ) * p

[HDOJ5439]Aggregated Counting(乱搞)

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5439 题意:按规则构造一个数列a a(1)=1 a(2)=2 a(2)=2 -------> 写两个2 --------> a()={1 2 2} a(3)=2 -------> 写两个3 --------> a()={1 2 2 3 3} a(4)=3 ------->写三个4 --------->a()={1 2 2 3 3 4 4 4} 以此类推 求f(f(n)),f(n

后缀数组 --- HDU 3518 Boring counting

Boring counting Problem's Link:   http://acm.hdu.edu.cn/showproblem.php?pid=3518 Mean: 给你一个字符串,让你求出有多少个子串(无重叠)至少出现了两次. analyse: 后缀数组中height数组的运用,一般这个数组用得很少. 总体思路:分组统计的思想:将相同前缀的后缀分在一个组,然后对于1到len/2的每一个固定长度进行统计ans. 首先我们先求一遍后缀数组,并把height数组求出来.height数组代表的

HDU 3518 Boring counting(后缀数组啊 求字符串中不重叠的重复出现至少两次的子串的个数)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3518 Problem Description 035 now faced a tough problem,his english teacher gives him a string,which consists with n lower case letter,he must figure out how many substrings appear at least twice,moreover

HDU 3079 Vowel Counting (水)

Vowel Counting Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1413    Accepted Submission(s): 1043 Problem Description The "Vowel-Counting-Word"(VCW), complies with the following conditio

hdu 5439 Ponds(长春网络赛——拓扑排序+搜索)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5438 Ponds Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 2837    Accepted Submission(s): 891 Problem Description Betty owns a lot of ponds, so