与巨
- description
- solution
- code
description
【题目描述】
定义无穷序列f:f1=1,fn=fn−1∗2+1f:f_1=1,f_n=f_{n-1}*2+1f:f1=1,fn=fn−1∗2+1
定义函数G(x)=minfi≥x(fi)G(x)=\min_{f_i\ge x}(f_i)G(x)=minfi≥x(fi)
定义dpc,0=0,dpc,i=max(dpc,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=0ndpc,i(mod998244353)\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∣≤107,1≤c≤1018,∑i=1T∣n∣≤1071\le T\le 10;1\le |n|\le 10^7,1\le c\le 10^{18},\sum_{i=1}^T|n|\le 10^71≤T≤10;1≤∣n∣≤107,1≤c≤1018,∑i=1T∣n∣≤107
solution
观察到fif_ifi的生成递推式,最后结果一定形如000..00011...111
设G(i)=2t+1−1G(i)=2^{t+1}-1G(i)=2t+1−1,G(i)G(i)G(i)必然是这种形式,ttt为二进制最高位
则x&G(i)x\&G(i)x&G(i)相当于xmod 2t+1x\ \text{mod}\ 2^{t+1}x mod 2t+1
则,有(i∗c)&G(i)=i⇔(i∗c)mod 2t+1=i⇔i∗(c−1)mod 2t+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
以2p∗q=c−12^p*q=c-12p∗q=c−1来重新表示,则iii必须含有因子2t+1−p2^{t+1-p}2t+1−p
设m=∣n∣m=|n|m=∣n∣,可以枚举ttt
-
t<m−1t<m-1t<m−1
则[2t,2t+1−1][2^t,2^{t+1}-1][2t,2t+1−1]内的所有数都在nnn之内,其最高位均为ttt
设g=t+1−pg=t+1-pg=t+1−p,那么iii含有因子2g2^g2g意味着iii的低ggg位全为000
这样的数为2t,2t+2g,...,2t+x∗2g2^t,2^t+2^g,...,2^t+x*2^g2t,2t+2g,...,2t+x∗2g 【2t+(x+1)2g=2t+12^t+(x+1)2^g=2^{t+1}2t+(x+1)2g=2t+1】
这是一个x+1x+1x+1项的等差数列,利用公式容易求得
同时每个数都会对最终答案贡献2g2^g2g次【对于G(i)=2aG(i)=2^aG(i)=2a,那么G(i+k,k∈[1,2a])=2a+1G(i+k,k\in[1,2^a])=2^{a+1}G(i+k,k∈[1,2a])=2a+1,2a+12^{a+1}2a+1都会贡献,一共是2a2^a2a】
-
t=m−1t=m-1t=m−1,由于2t+1>n2^{t+1}>n2t+1>n,但需要满足2t+x∗2t≤n⇒x=⌊n2g⌋−2t−g2^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+1x+1x+1项的等差数列同样方法计算贡献后,最后一项被计算了2g2^g2g次,计数范围为[2t+x∗2g,2t+(x+1)∗2g−1][2^t+x*2^g,2^t+(x+1)*2^g-1][2t+x∗2g,2t+(x+1)∗2g−1]
此时多计数了2t+(x+1)∗2g−1−n2^t+(x+1)*2^g-1-n2t+(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^gint 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;
}