HDU 5439 Aggregated Counting
2015-09-14 17:49
211 查看
传送门
找规律可以发现:ans=∑i∗a[i]i=1..n
即原数列中所有不超过n的数的和
容易发现一个数x最后出现位置即数列中前x项之和。
所以答案就是最后一个n的位置之前所有数的和。
找规律可以发现: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; }
相关文章推荐
- 限制文本框输入指定字符
- c# yield
- iOS开发:利用SDWebImage实现图片加载与缓存
- C/C++中的输入与输出及如何读取一行文本
- Android开发时你遇到过什么相见恨晚的工具或网站?
- C/C++中的void和void*
- Asp.Net_button样式对不齐
- Asp.Net_WebFrom
- 【Linux网络编程】 网络协议入门
- 大规模并发问题
- 【PA2014】【BZOJ3709】Bohater
- 文章标题
- Mysql 可用性
- MVC Action返回Json
- 判断Activity是否运行
- 二分查找
- war包部署到Tomcat服务器
- fedora22下安装配置hbase
- C/C++中随机数的获取: 伪随机函数
- C/C++面试题-1