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. npm config 删除变量

    问题 安装npm时,使用npm config set 命令重新设置了变量,但是设置变量时少了个空格,设置错了.使用npm config ls -l 查看环境变量 添加错的这一个,应该如何删除? 解决 ...

  2. MS-DOS 6.22 +Vim+masm 汇编环境

    安装vim 个人习惯用 vim 编辑,因此稍微折腾了一下.不用这么麻烦直接用 edit 编辑也是可以的. 原来安装的 MS-DOS 7.10 虚拟机安装好vim后无法运行,所以改用了 MS-DOS 6 ...

  3. 【BZOJ5314】[JSOI2018]潜入行动(动态规划)

    [BZOJ5314][JSOI2018]潜入行动(动态规划) 题面 BZOJ 洛谷 题解 不难想到一个沙雕\(dp\),设\(f[i][j][0/1][0/1]\)表示当前点\(i\),子树中一共放了 ...

  4. c# double decimal

    两种类型 double范围比decimal大,精度比之低 类型 大致范围 精度 .NET Framework 类型 double ±5.0 × 10−324 到 ±1.7 × 10308 15 到 1 ...

  5. HDU1542-Atlantis【离散化&线段树&扫描线】个人认为很全面的详解

    刚上大一的时候见过这种题,感觉好牛逼哇,这都能算 如今已经不打了,不过适当写写题保持思维活跃度还是不错的,又碰到这种题了,想把它弄出来 说实话,智商不够,看了很多解析,花了4.5个小时才弄明白 网上好 ...

  6. bzoj1014 火星人 (hash+splay+二分答案)

    求公共前缀的问题可以用hash+二分来解决,但这个是动态的,所以我们用平衡树来维护区间的hash值 复杂度$O(mlog^2n)$ #include<bits/stdc++.h> #def ...

  7. luogu3278/bzoj3323 多项式的运算 (splay)

    mulx的操作,其实就是给r+1的系数+=r的系数,然后删掉r,把l~r-1向右移一位,再插一个0到原来的位置 splay维护区间加和区间乘就好了 (一定要注意做事的顺序,一件事都做完了再去做别的,否 ...

  8. Hyper-V

    docker与vm同时安装,会导致虚拟机无法启动及网络不通等问题,解决方法分为两步. 1.在网络连接中禁用vEthernet连接. 2.控制面板>程序>程序和功能中 >启用或关闭wi ...

  9. 如何查看本地电脑ip

    1.快捷键 win+R打开命令窗口 输入 ipconfig查看你电脑的ip 2.输入netstat -an ,查看当前所有连接端口,显示所有的有效连接信息列表,包括已建立的连接(ESTABLISHED ...

  10. 洛谷P2824 排序

    解:splay + 线段树合并,分裂. 首先有个乱搞做法是外层拿splay维护,有序区间缩成splay上一个节点.内层再开个数据结构支持合并分裂有序集合. 内层我一开始想的是splay,然后就没有复杂 ...