牛客网多校第四场-----C Chiaki Sequence Reloaded

转载:https://blog.csdn.net/xianpingping/article/details/81292942
链接:https://www.nowcoder.com/acm/contest/142/C
来源:牛客网

Chiaki Sequence Reloaded
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld
题目描述
Chiaki is interested in an infinite sequence a1, a2, a3, …, which defined as follows:
这里写图片描述
Chiaki would like to know the sum of the first n terms of the sequence, i.e. . As this number may be very large, Chiaki is only interested in its remainder modulo (109 + 7).
输入描述:
There are multiple test cases. The first line of input contains an integer T (1 ≤ T ≤ 105), indicating the number of test cases. For each test case:
The first line contains an integer n (1 ≤ n ≤ 1018).
输出描述:
For each test case, output an integer denoting the answer.
示例1
输入
复制
10
1
2
3
4
5
6
7
8
9
10
输出
复制
0
1
2
2
4
4
6
7
8
11

这里写图片描述
思路:这道题的规律真的是难想。
打表可知,a【i】的值就是i转化成二进制后,相邻两位的值相同就加一,否则减一。
然后就可以用数位dp来写了。
用dp【i】【j】【k】表示第i位,当前位的值是j,当前的和是k
由于k的取值范围是【-64,64】所以用abs(和-64)来代替。
采用数位DP的记忆化模板来写

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
LL dp[64][3][129];
int a[64];
LL dfs(int len,bool shangxian,int pre,int sum)
{
    if(len == 0){
        return abs(sum - 64);
    }
    if(!shangxian && dp[len][pre][sum] != -1){
        return dp[len][pre][sum];
    }
    LL ans = 0;
    int maxn = shangxian ? a[len] : 1;
    for(int i = 0;i <= maxn;++i)
    {
        if(pre == 2){
            if(i){
                ans += dfs(len - 1,shangxian && i == a[len],i,sum);
            }
            else{
                ans += dfs(len - 1,shangxian && i == a[len],pre,sum);
            }
        }
        else{
            if(i == pre){
                ans += dfs(len - 1,shangxian && i == a[len],i,sum + 1);
            }
            else{
                ans += dfs(len - 1,shangxian && i == a[len],i,sum - 1);
            }
        }
        ans %= mod;
    }
    ans %= mod;
    if(!shangxian){
        return dp[len][pre][sum] = ans;
    }
    return ans;
}

LL solve(LL n)
{
    int k = 0;
    while(n)
    {
        a[++k] = n % 2;
        n /= 2;
    }
    return dfs(k,true,2,64);
}

int main()
{
    int t;
    //dp初始化必须在这里,在其他地方会超时,因为t组数据中计算完一个可以为下一个提供用处
    memset(dp,-1,sizeof(dp));
    while(~scanf("%d",&t))
    {
        while(t--)
        {
            LL n;
            scanf("%lld",&n);
            printf("%lld\n",solve(n) % mod);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_36386435/article/details/81325518