HDU 5439 Aggregated Counting
題目大意:
由1開始不斷往數(shù)組中添加數(shù)
就是按照當前所在位置所在的數(shù)表示的個數(shù)添加這個數(shù)目的數(shù)
1 2 2 3 3 后面因為要填4,而4號位置為3,說明之后要填3個4
問題就是給定一個n,找到n出現(xiàn)的最后位置p,再找p出現(xiàn)的最后位置即可
?
這里可以考慮先找到g[i]表示 i 連續(xù)出現(xiàn)了多少次
這里想一下的話,因為g[i] 相當于 i 位置出現(xiàn)的數(shù)
所以g[i]也滿足這個序列
令f[i] 表示 i 出現(xiàn)的最后位置,也就是1~i的總個數(shù)
后面去計算g[i]的時候就可以考慮的是找到第 i 個位置在那個f[]的區(qū)間內 ?, 如果f[k-1]< i <= f[k]
那么說明此時 g[i] = k
那么就可以logn的復雜度計算g[n]了
?
要計算最后的答案,要考慮的是,給定的n,找到最后出現(xiàn)的p,中間長度 p = g[1]+g[2]....+g[p]
然后再找對應的ans ,那么每次增加的g[i],就會讓整個序列 的長度增加 i*g[i]
?i*g[i] 可以理解為的是,長度為i的數(shù)量有g[i]個,?所以總長度是i*g[i]
所以ans = sigma(i*g[i]) i<=n
那么對于n <= 1e9
那么大致計算一下會發(fā)現(xiàn)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]這一段區(qū)間內的所有長度都被用到了
所以之前預處理這個長度的前綴和 sum[]
對于每一個長度 i ,他出現(xiàn)的次數(shù)都是 f[i]-f[i-1]
sigma(n*g[n]) f[i-1]<n<=f[i] ?-> g[n] = i
那么答案就是 i*等差數(shù)列了,記得取模(⊙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++) //這個區(qū)間每個長度都為pos 50 { 51 ret = (ret+(ll)i*pos)%MOD; 52 } 53 printf("%I64d\n" , ret); 54 } 55 return 0; 56 }?
轉載于:https://www.cnblogs.com/CSU3901130321/p/4805973.html
總結
以上是生活随笔為你收集整理的HDU 5439 Aggregated Counting的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MariaDb数据库管理系统的学习(一)
- 下一篇: 为什么需要多线程