专栏文章

不卡单 log 这一块

CF1423J题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@min1rgl4
此快照首次捕获于
2025/12/01 19:09
3 个月前
此快照最后确认于
2025/12/01 19:09
3 个月前
查看原文
我还寻思这题怎么是个 *2400 呢,合着我的做法就不是预期解啊。
注意到 7=2317 = 2^3 - 1,考虑二进制。
对于 xkx^k 项,其对于第 00(k1)(k-1) 位的贡献为 00,而对于第 kk 位,第 k+1k+1 位和第 k+2k+2 位的贡献可以在 {0,1}\{0,1\} 中任选,且互相独立。
因此,考虑从低到高讨论每一位。每一位最多有 33 个互相独立的数作出贡献。记 f(i,j)f(i,j) 表示考虑低 ii 位,且在第 ii 位上遗留进位为 jj 的方案数。可以得到 jj 为不超过 22 的自然数。
对于 i=0i = 0,有 f(0,0)=1f(0,0) = 1f(0,1)=0f(0,1) = 0f(0,2)=0f(0,2) = 0。对于 i=1i = 1,若 mm 这一位上是 00,则两种可能的方案为两个位置均填 00 或填 11。前者不进位,后者进 11 位,故 f(1,0)=1f(1,0) = 1f(1,1)=1f(1,1) = 1f(1,2)=0f(1,2) = 0。若 mm 这一位上是 11,则这两个位置上必须一个 11 一个 00,故 f(1,0)=2f(1,0) = 2f(1,1)=0f(1,1) = 0f(1,2)=0f(1,2) = 0
对于后面的位置,若 mm 这一位上是 00,则 f(i,0)=f(i1,0)f(i,0) = f(i-1,0)(全部填 00),f(i,1)=3f(i1,0)+3f(i1,1)+f(i1,2)f(i,1) = 3f(i-1,0) + 3f(i-1,1) + f(i-1,2)(分别为两个填 11,一个填 11,不填 11),f(i,2)=f(i1,1)+3f(i1,2)f(i,2) = f(i-1,1) + 3f(i-1,2)。(分别为都填 11 和填两个 11)。否则, f(i,0)=3f(i1,0)+f(i1,1)f(i,0) = 3f(i-1,0) + f(i-1,1)(分别为填一个 11 和不填 11),f(i,1)=f(i1,0)+3f(i1,1)+3f(i1,2)f(i,1) = f(i-1,0) + 3f(i-1,1) + 3f(i-1,2)(分别为填三个 11,填两个 11 和填一个 11),f(i,2)=f(i1,2)f(i,2) = f(i-1,2)(都填 11)。
mm 的最高位为 nn,则最后取 f(n,0)f(n,0) 极为答案。
时间复杂度 O(logm)O(\log m)
CPP
#include<bits/stdc++.h>
using namespace std;
const int Maxw=63,mod=1000000007;
int T;
long long m;
long long dp[Maxw+3][3],ans;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin>>T;
    while(T--)
    {
        cin>>m;
        if(m==1)
        {
            cout<<1<<"\n";
            continue;
        }
        dp[0][0]=1;
        if((m>>1)&1) dp[1][0]=2,dp[1][1]=0,dp[1][2]=0;
        else dp[1][0]=1,dp[1][1]=1,dp[1][2]=0;
        ans=dp[1][0];
        for(int i=2;(1ll<<i)<=m;i++)
        {
            if((m>>i)&1)
            {
                dp[i][0]=(dp[i-1][0]*3+dp[i-1][1])%mod;
                dp[i][1]=(dp[i-1][0]+dp[i-1][1]*3+dp[i-1][2]*3)%mod;
                dp[i][2]=dp[i-1][2];
            }
            else
            {
                dp[i][0]=dp[i-1][0];
                dp[i][1]=(dp[i-1][0]*3+dp[i-1][1]*3+dp[i-1][2])%mod;
                dp[i][2]=(dp[i-1][1]+dp[i-1][2]*3)%mod;
            }
            ans=dp[i][0];
        }
        cout<<ans<<"\n";
    }
    return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...