description
【题目描述】
定义无穷序列
f
:
f
1
=
1
,
f
n
=
f
n
−
1
∗
2
+
1
f:f_1=1,f_n=f_{n-1}*2+1
f:f1=1,fn=fn−1∗2+1
定义函数 G ( x ) = min f i ≥ x ( f i ) G(x)=\min_{f_i\ge x}(f_i) G(x)=minfi≥x(fi)
定义 d p c , 0 = 0 , d p c , i = max ( d p c , i − 1 , [ ( ( i ∗ c ) & G ( i ) ) = i ] ∗ i ) dp_{c,0}=0,dp_{c,i}=\max(dp_{c,i-1},\big[\big((i*c)\&G(i)\big)=i\big]*i) dpc,0=0,dpc,i=max(dpc,i−1,[((i∗c)&G(i))=i]∗i)
求 ∑ i = 0 n d p c , i ( m o d 998244353 ) \sum_{i=0}^ndp_{c,i}\pmod {998244353} ∑i=0ndpc,i(mod998244353)
【输入格式】
第一行输入一个整数T,表示测试用例的组数。
每组测试用例输入一行包含两个整数n, c。
其中𝐧以二进制形式表示,且𝐧不含有前导 0。
【输出格式】
对于每组测试用例输出一行一个整数表示答案。
【样例 1 输入】
5
1001 1
11111 1
101010111101 8999
10100101111010101 799
10010010 233
【样例 1 输出】
45
496
2835797
707482963
9940
【数据范围】
1 ≤ T ≤ 10 ; 1 ≤ ∣ n ∣ ≤ 1 0 7 , 1 ≤ c ≤ 1 0 18 , ∑ i = 1 T ∣ n ∣ ≤ 1 0 7 1\le T\le 10;1\le |n|\le 10^7,1\le c\le 10^{18},\sum_{i=1}^T|n|\le 10^7 1≤T≤10;1≤∣n∣≤107,1≤c≤1018,∑i=1T∣n∣≤107
solution
观察到
f
i
f_i
fi的生成递推式,最后结果一定形如000..00011...111
设 G ( i ) = 2 t + 1 − 1 G(i)=2^{t+1}-1 G(i)=2t+1−1, G ( i ) G(i) G(i)必然是这种形式, t t t为二进制最高位
则 x & G ( i ) x\&G(i) x&G(i)相当于 x mod 2 t + 1 x\ \text{mod}\ 2^{t+1} x mod 2t+1
则,有 ( i ∗ c ) & G ( i ) = i ⇔ ( i ∗ c ) mod 2 t + 1 = i ⇔ i ∗ ( c − 1 ) mod 2 t + 1 = 0 (i*c)\&G(i)=i\Leftrightarrow (i*c)\ \text{mod}\ 2^{t+1}=i\Leftrightarrow i*(c-1)\ \text{mod}\ 2^{t+1}=0 (i∗c)&G(i)=i⇔(i∗c) mod 2t+1=i⇔i∗(c−1) mod 2t+1=0
以 2 p ∗ q = c − 1 2^p*q=c-1 2p∗q=c−1来重新表示,则 i i i必须含有因子 2 t + 1 − p 2^{t+1-p} 2t+1−p
设 m = ∣ n ∣ m=|n| m=∣n∣,可以枚举 t t t
-
t < m − 1 t<m-1 t<m−1
则 [ 2 t , 2 t + 1 − 1 ] [2^t,2^{t+1}-1] [2t,2t+1−1]内的所有数都在 n n n之内,其最高位均为 t t t
设 g = t + 1 − p g=t+1-p g=t+1−p,那么 i i i含有因子 2 g 2^g 2g意味着 i i i的低 g g g位全为 0 0 0
这样的数为 2 t , 2 t + 2 g , . . . , 2 t + x ∗ 2 g 2^t,2^t+2^g,...,2^t+x*2^g 2t,2t+2g,...,2t+x∗2g 【 2 t + ( x + 1 ) 2 g = 2 t + 1 2^t+(x+1)2^g=2^{t+1} 2t+(x+1)2g=2t+1】
这是一个 x + 1 x+1 x+1项的等差数列,利用公式容易求得
同时每个数都会对最终答案贡献 2 g 2^g 2g次【对于 G ( i ) = 2 a G(i)=2^a G(i)=2a,那么 G ( i + k , k ∈ [ 1 , 2 a ] ) = 2 a + 1 G(i+k,k\in[1,2^a])=2^{a+1} G(i+k,k∈[1,2a])=2a+1, 2 a + 1 2^{a+1} 2a+1都会贡献,一共是 2 a 2^a 2a】
-
t = m − 1 t=m-1 t=m−1,由于 2 t + 1 > n 2^{t+1}>n 2t+1>n,但需要满足 2 t + x ∗ 2 t ≤ n ⇒ x = ⌊ n 2 g ⌋ − 2 t − g 2^t+x*2^t\le n\Rightarrow x=\lfloor\frac{n}{2^g}\rfloor-2^{t-g} 2t+x∗2t≤n⇒x=⌊2gn⌋−2t−g
对这个 x + 1 x+1 x+1项的等差数列同样方法计算贡献后,最后一项被计算了 2 g 2^g 2g次,计数范围为 [ 2 t + x ∗ 2 g , 2 t + ( x + 1 ) ∗ 2 g − 1 ] [2^t+x*2^g,2^t+(x+1)*2^g-1] [2t+x∗2g,2t+(x+1)∗2g−1]
此时多计数了 2 t + ( x + 1 ) ∗ 2 g − 1 − n 2^t+(x+1)*2^g-1-n 2t+(x+1)∗2g−1−n次,减去多的贡献即可
code
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define int long long
#define mod 998244353
#define maxn 10000005
int mi[maxn];
char s[maxn];
const int inv2 = ( mod + 1 ) >> 1;
int calc( int a, int d, int n ) {
return ( a * n % mod + n * ( n - 1 ) % mod * d % mod * inv2 % mod ) % mod;
}
signed main() {
freopen( "and.in", "r", stdin );
freopen( "and.out", "w", stdout );
mi[0] = 1;
for( int i = 1;i < maxn;i ++ ) mi[i] = ( mi[i - 1] << 1 ) % mod;
int T, n, c;
scanf( "%lld", &T );
while( T -- ) {
scanf( "%s %lld", s + 1, &c );
n = strlen( s + 1 );
c --;
int ans = 0;
if( ! c ) {
for( int i = 1;i <= n;i ++ )
ans = ( ( ans << 1 ) + ( s[i] ^ 48 ) ) % mod;
printf( "%lld\n", ans * ( ans + 1 ) % mod * inv2 % mod );
}
else {
if( c & 1 ) { printf( "0\n" ); continue; }
else {
int p = 0;
while( ! ( c & 1 ) ) c >>= 1, p ++;
for( int t = 0;t < n;t ++ ) {
int g = max( 0ll, t + 1 - p );
if( t < n - 1 )
ans = ( ans + mi[g] * calc( mi[t], mi[g], mi[t + 1 - g] - mi[t - g] ) ) % mod;
else {
int k = 0;
for( int i = 1;i <= n - g;i ++ ) k = ( ( k << 1 ) + ( s[i] ^ 48 ) ) % mod;//n/2^g下取整
int x = ( k - mi[t - g] ) % mod;
ans = ( ans + mi[g] * calc( mi[t], mi[g], x + 1 ) ) % mod;//x=k-2^{t-g}=k-mi[t-g] x+1项
int lst = ( mi[t] + x * mi[g] ) % mod;//计算末项 2^t+x*2^g
int l = 0;
int r = ( lst + mi[g] - 1 ) % mod;//末项的下一项 2^t+(x+1)*2^g 还有一个-1
for( int i = 1;i <= n;i ++ ) l = ( ( l << 1 ) + ( s[i] ^ 48 ) ) % mod; //-n
ans = ( ans - ( r - l ) * lst ) % mod;
}
}
}
printf( "%lld\n", ( ans + mod ) % mod );
}
}
return 0;
}