牛客NOIP2021提高组OI赛前模拟赛第一场T3——与巨(数学)
與巨
- 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)=min?fi≥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=0n?dpc,i?(mod998244353)
【輸入格式】
第一行輸入一個整數T,表示測試用例的組數。
每組測試用例輸入一行包含兩個整數n, c。
其中𝐧以二進制形式表示,且𝐧不含有前導 0。
【輸出格式】
對于每組測試用例輸出一行一個整數表示答案。
【樣例 1 輸入】
【樣例 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; }總結
以上是生活随笔為你收集整理的牛客NOIP2021提高组OI赛前模拟赛第一场T3——与巨(数学)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Communicator可以多点同时Lo
- 下一篇: 《异度神剑2》与犹太教卡巴拉略考