http://acm.hdu.edu.cn/showproblem.php?pid=6304

题意

给出一个数列的定义,a[1]=a[2]=1,a[n]=a[n-a[n-1]]+a[n-1-a[n-2]](n>=3)。求前n项和,n<=1e18。

分析

一看就是得打表找规律或推公式的题目。

先把a[i]打出来: 1 1 2 2 3 4 4 4 5 6 6...

乍眼一看每个数字出现的次数有点意思,于是打出每个数出现次数:

数值   1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16

次数   2  2  1  3  1  2  1  4  1   2    1    3    1    2    1    5

感觉第一个1很不和谐啊,先忽略这个1看看:

数值   1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16

次数   1  2  1  3  1  2  1  4  1   2    1    3    1    2    1    5

可以看到前2^i个数的出现次数是由前2^(i-1)个数复制两次,并把2^i的次数+1得到的。

这样就得到数值出现次数的规律了,设cnt[i]为前2^i个数的次数之和,那么cnt[i]=2*cnt[i-1]+1。

有了cnt[i],对于一个下标n,可以求出a[n]的值,相反也可以求出值为a[n]的第一个位置。

然后怎么求前n项和呢?把相同出现次数的值输出看看:

1-- 1,3,5,7,9....

2-- 2,6,10,14...

3-- 4,12,20,28...

4-- 8,24,40,56...

....

很明显的规律,对于次数k,对应数值形成一个首项为2^(k-1),公差为2^k的等差数列。这个等差数列的每个值都出现k次。

所以,可以枚举次数,计算以a[n]为上界的项数,再把这个等差数列的和*次数加到答案中。

需要注意,计算等差数列时不能把a[n]算进去,因为a[n]出现的次数在n的限制下是不完全的,需要另外计算,这时就用到上面计算的a[n]出现的第一个位置了,由此算出a[n]实际出现的次数,再加到答案中。

由于数据是ll级别,出现相乘时不要忘记先模一下。

其它细节看代码。

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
const ll mod = 1e9 + ; ll cnt[],p[];
//预处理2^i和cnt[i]
void init(){
cnt[]=p[]=;
for(int i=;i<=;i++) cnt[i]=*cnt[i-]+,p[i]=*p[i-];
}
//计算a[n]的数值
ll caln(ll n){
if(n==) return ;//特殊处理
n--;//由于规律从实际的第二个开始计算
ll an = ;
for(int i=;i>=;i--){
while(cnt[i]<=n){
n-=cnt[i];
an+=p[i];
}
}
return an;
}
//根据a[n]计算最早出现的位置
ll gps(ll an){
if(an==) return ;
an--; //同上
ll pos=;
for(int i=;i>=;i--){
while(p[i]<=an){
an-=p[i];
pos+=cnt[i];
}
}
return pos+;
}
int main() {
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif // LOCAL
int T;
ll n;
scanf("%d",&T);
init();
ll _inv = ;//2的逆元
while(T--){
scanf("%lld",&n);
ll an = caln(n);
ll cnt = n - gps(an);//a[n]出现的实际次数
ll ans = ;
for(int i=;p[i-]<=an;i++){//枚举次数,终结条件为某个等差数列的首项大于a[n]
ll x1 = p[i-]; //首项
ll d = p[i]; //公差
//项数。注意,正常的项数应该是((an-x1)/d+1),但这里不能保证a[n]全部出现了,
//所以当((an-x1)%d==0)时说明a[n]位于当前的等差数列中,需要根据实际个数来计算,于是不+1
ll num = ((an-x1)%d==)?((an-x1)/d):((an-x1)/d+);
ll xn = x1 + (num-)*d; //尾项
ll sum = (x1%mod+xn%mod)%mod*(num%mod)%mod*_inv%mod; //等差数列前num项和
ans = (ans+i*sum%mod)%mod; //加入答案,共出现i次
if((an-x1)%d==)
ans=(ans+cnt*(an%mod)%mod)%mod; //a[n]位于此数列,特别计算一下。
}
printf("%lld\n",ans+);//由于计算中忽略了第一项1,最后加上
}
return ;
}

HDU - 6304(2018 Multi-University Training Contest 1) Chiaki Sequence Revisited(数学+思维)的更多相关文章

  1. 2018 杭电多校1 - Chiaki Sequence Revisited

    题目链接 Problem Description Chiaki is interested in an infinite sequence $$$a_1,a_2,a_3,...,$$$ which i ...

  2. hdu 4915 Parenthese sequence--2014 Multi-University Training Contest 5

    主题链接:http://acm.hdu.edu.cn/showproblem.php?pid=4915 Parenthese sequence Time Limit: 2000/1000 MS (Ja ...

  3. hdu 4902 Nice boat--2014 Multi-University Training Contest 4

    题目链接:http://acm.hdu.edu.cn/showproblem.php? pid=4902 Nice boat Time Limit: 30000/15000 MS (Java/Othe ...

  4. hdu 4925 Apple Tree--2014 Multi-University Training Contest 6

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4925 Apple Tree Time Limit: 2000/1000 MS (Java/Others ...

  5. HDU校赛 | 2019 Multi-University Training Contest 6

    2019 Multi-University Training Contest 6 http://acm.hdu.edu.cn/contests/contest_show.php?cid=853 100 ...

  6. HDU校赛 | 2019 Multi-University Training Contest 5

    2019 Multi-University Training Contest 5 http://acm.hdu.edu.cn/contests/contest_show.php?cid=852 100 ...

  7. HDU校赛 | 2019 Multi-University Training Contest 4

    2019 Multi-University Training Contest 4 http://acm.hdu.edu.cn/contests/contest_show.php?cid=851 100 ...

  8. HDU校赛 | 2019 Multi-University Training Contest 3

    2019 Multi-University Training Contest 3 http://acm.hdu.edu.cn/contests/contest_show.php?cid=850 100 ...

  9. HDU校赛 | 2019 Multi-University Training Contest 2

    2019 Multi-University Training Contest 2 http://acm.hdu.edu.cn/contests/contest_show.php?cid=849 100 ...

随机推荐

  1. 【BZOJ3132】【TYVJ1716】上帝造题的七分钟 二维树状数组

    题目大意 维护一个\(n\times m\)的矩阵,有两种操作: \(1~x_1~y_1~x_2~y_2~v\):把\((a,b),(c,d)\)为顶点的矩形区域内的所有数字加上\(v\). \(2~ ...

  2. Hdoj 1392.Surround the Trees 题解

    Problem Description There are a lot of trees in an area. A peasant wants to buy a rope to surround a ...

  3. 平衡树splay学习笔记#2

    讲一下另外的所有操作(指的是普通平衡树中的其他操作) 前一篇的学习笔记连接:[传送门],结尾会带上完整的代码. 操作1,pushup操作 之前学习过线段树,都知道子节点的信息需要更新到父亲节点上. 因 ...

  4. angular2路由与express路由冲突的问题

    angular2的路由定义了一个/a,如果走angular的路由没问题,如果直接访问/a就会出现cannot GET /a的错误,原因就是express的路由问题. 所以路由走angular2,那ex ...

  5. ava EE 7 - Injection into Runnable/Callable object ejb entityManager Concurrency ManagedExecutorService 异步调用如何获取context

    或者直接把 MyTask类内嵌如MyBean中,这样可以在myBean中inject 数据库连接,在内嵌类内访问. java ee 引入了并发执行.因为是在服务器执行并发,所以要用java ee包里面 ...

  6. Gnome添加Open with Code菜单

    解决方法 测试环境: Manjaro Linux Rolling at 2018-08-31 19:04:49 Microsoft Visual Stdio Code 1.26.1 Bulid: 20 ...

  7. gallery

    效果如下 目录如下 代码如下: //index.html <!DOCTYPE html> <html> <head> <meta charset=" ...

  8. 斯坦福大学公开课机器学习: machine learning system design | prioritizing what to work on : spam classification example(设计复杂机器学习系统的主要问题及构建复杂的机器学习系统的建议)

    当我们在进行机器学习时着重要考虑什么问题.以垃圾邮件分类为例子.假如你想建立一个垃圾邮件分类器,看这些垃圾邮件与非垃圾邮件的例子.左边这封邮件想向你推销东西.注意这封垃圾邮件有意的拼错一些单词,就像M ...

  9. log4net 开启内部调试

    大家都在用LOG4NET,但这是封装好的,在有时我们找不到原因时会想到是不是发生在里面,比如,配置好了日志记录到数据库(Mysql.Oracle.Sql Server)等,但就是记录不上,又找不到原因 ...

  10. curl 出现错误的调试方法

    private function httpGet($url) { $curl = curl_init(); curl_setopt($curl, CURLOPT_RETURNTRANSFER, tru ...