牛客网暑期ACM多校训练营(第四场)C. Chiaki Sequence Reloaded 数位DP

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sinat_35406909/article/details/82466748

Problem C. Chiaki Sequence Reloaded

Input file: standard input
Output file: standard output
Time limit: 1 seconds
Memory limit: 256 mebibytes

Problem Description

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).

Input

There are multiple test cases. The first line of input contains an integer T (1 ≤ T ≤ 10^5), indicating the number of test cases. For each test case:
The first line contains an integer n (1 ≤ n ≤ 10^18).

Output

For each test case, output an integer denoting the answer.

Sample Input Sample Output
10
1
2
3
4
5
6
7
8
9
10
0
1
2
2
4
4
6
7
8
11




观察给出的递推公式,发现
a i a i 2 = 1 i 二进制的后两位相等
a i a i 2 = 1 i 二进制的后两位不等
由此,可以对小于 n 的元素做数位DP。
设dp[len][last][sum]表示当前dp到第len位,最后一位二进制位是last,且之前dp的数位对答案的贡献和是sum.
则可以很容易的用数位DP算出答案。

#include <cstdio>
#include <iostream>
#include <string.h>
#include <string>
#include <map>
#include <queue>
#include <deque>
#include <vector>
#include <set>
#include <algorithm>
#include <math.h>
#include <cmath>
#include <stack>
#include <iomanip>
#define pb push_back
#define mem0(a) memset(a,0,sizeof(a))
#define meminf(a) memset(a,0x3f,sizeof(a))
using namespace std;
typedef long long ll;
typedef long double ld;
typedef double db;
typedef pair<int,int> pp;
const int maxn=105,inf=0x3f3f3f3f;
const ll llinf=0x3f3f3f3f3f3f3f3f,mod=1e9+7;
const ld pi=acos(-1.0L);
ll dp[75][2][150],num[100];

ll dfs(ll len,ll last,ll sum,bool HaveLimit,bool zero) {
    if (!len)
        if (!zero) return 0; else return abs(sum);
    if (!HaveLimit&&dp[len][last][sum+64]!=-1&&zero)
        return dp[len][last][sum+64];

    int limit,i,ext;
    if (HaveLimit) limit=num[len]; else limit=1;
    ll ans=0;
    for (i=0;i<=limit;i++) {
        if (!zero) ext=0; else if (i==last) ext=1; else ext=-1;
        ans+=dfs(len-1,i,sum+ext,HaveLimit&&i==limit,zero|i);
        ans%=mod;
    }
    if (!HaveLimit&&zero) dp[len][last][sum+64]=ans;
    return ans;
}

ll solve(ll limit) {
    if (limit==-1) return 0;
    ll k=limit,cnt=0;
    while (k>0) {
        cnt++;
        num[cnt]=k%2;
        k/=2;
    }
    ll ans=0;
    ans=dfs(cnt,2,0,1,0);
    return ans;
}

int main() {
    int cas;
    scanf("%d",&cas);
    memset(dp,-1,sizeof(dp));
    while (cas--) {
        ll n;
        scanf("%lld",&n);
        ll ans=solve(n);
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sinat_35406909/article/details/82466748