您的位置:首页 > 其它

HDU 5439 Aggregated Counting

2015-09-14 17:49 211 查看
传送门

找规律可以发现:ans=∑i∗a[i]i=1..n

即原数列中所有不超过n的数的和

容易发现一个数x最后出现位置即数列中前x项之和。

所以答案就是最后一个n的位置之前所有数的和。

#include <bits/stdc++.h>
using namespace std;
#define prt(k) cerr<<#k" = "<<k<<endl
typedef long long ll;
typedef long long LL;
const int N = 450100;
int a
; // a[i] : i出现次数
const LL mod = 1e9+7;
LL mul(LL a, LL n)
{
a %= mod, n %= mod;
LL r = 0;
for (; n>0; n>>=1, a=(a+a)%mod) if (n&1) r=(r+a)%mod;
return r;
}
ll pmod(ll a, ll n)
{
ll r = 1; for (; n>0; n>>=1, a=a*a%mod) if (n&1) r=r*a%mod;
return r;
}
int n, m;
LL dp
;
int s
;
int main()
{
m = 0;
a[++m] = 1;
a[++m] = 2;
a[++m] = 2;
s[1] = 1;
s[2] = 3;
LL inv2 = pmod(2, mod-2);
for (int n=3;m<N-1 && n<N;n++) {
for (int i=0;m<N-1 && i<a
;i++) {
if (m == N-1) break;
a[++m] = n;
}
}
s[0] = 0;
for (int i=1;i<N;i++) s[i]=s[i-1]+a[i];
dp[0] = 0;
for (int i=1;i<N;i++) {
dp[i] = dp[i-1];
LL t = mul(i, s[i-1] + s[i] + 1);
t = mul(t, s[i] - s[i-1] + mod);
t = mul(t, inv2);
dp[i] = (dp[i] + t) % mod;
}
int re; cin>>re;
while (re--) {
scanf("%d", &n);
int id  = upper_bound(s+1, s+N, n) - s - 1;
LL ans = dp[id];
LL t = mul(s[id] + n + 1, id + 1);
t = mul(t, n - s[id] + mod);
t = mul(t, inv2);
ans = (ans + t) % mod;
printf("%I64d\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: