【HDOJ6304】Chiaki Sequence Revisited(数学)

题意:
给定一个序列a,定义a[1]=a[2]=1,a[n]=a[n-a[n-1]]+a[n-1-a[n-2]](n>=3),求该序列的前n项和是多少,结果对 1e9+7 取模

n<=1e18

思路:OEIS没通项,打表找规律

除第一个1之外

1 3 5 7出现了1次

2 6 10 14出现了2次

4 12 20 28出现了3次

8 24 40 56出现了4次

先算出最多出现次数,然后对于出现次数相同的数用等差数列求和

余下的暴力计算

队友lyy写的

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cmath>
 5 using namespace std;
 6 typedef long long ll;
 7 const int mod=1000000007;
 8 int cas,i,j;
 9 ll n,inv,ans[100];
10 ll quickmi(ll x,ll y){
11     ll ans=1;
12     while (y){
13         if (y&1)ans=ans*x%mod;
14         x=x*x%mod;
15         y>>=1;
16     }
17     return ans;
18 }
19 ll calc(ll n){
20     if (!n)return 0;
21     ll mi=log(n+1)/log(2);
22     ll tmp=(1ll<<(mi-1))%mod;
23     n-=(1ll<<mi)-1;
24     return (n%mod*tmp%mod+calc(n)+ans[mi])%mod;
25 }
26 int main(){
27     inv=quickmi(4,mod-2);
28     ans[1]=1;
29     for (i=2;i<=64;i++){
30         ll tmp=1ll<<(i-1);
31         ll Tmp=tmp%mod;
32         Tmp=Tmp*Tmp%mod*inv%mod;
33         for (j=1;j<=i;j++){
34             ans[i]=(ans[i]+(1ll<<(j-1))%mod*j%mod*Tmp%mod)%mod;
35             if (j!=i-1)Tmp=Tmp*inv%mod;
36         }
37     }
38     scanf("%d",&cas);
39     while (cas--){
40         scanf("%lld",&n);
41         printf("%lld\n",calc(n-1)+1);
42     }
43 }

 

posted on 2018-07-31 10:13  myx12345  阅读(203)  评论(0编辑  收藏  举报

导航