[atARC135F]Delete 1,4,7,...
记$n_{k}$表示经过$k$轮操作后的元素个数,显然$n_{k}=\lfloor\frac{2n_{k-1}}{3}\rfloor$(初始$n_{0}=n$)
记$f^{k}(i)$表示$k$轮操作后的第$i$个元素在操作前的位置,显然$f^{k}(i)=\lceil\frac{3f^{k-1}(i)}{2}\rceil$
问题即求$\sum_{i=1}^{n_{k}}f^{k}(i)$,暴力计算时间复杂度为$o(nk\cdot (\frac{2}{3})^{k})$
另一方面,注意到$f^{k}(i+2^{k})=f^{k}(i)+3^{k}$,具体可以归纳证明
进一步的,折半取$x+y=k$,显然$f^{k}(i)=f^{x}(f^{y}(i))$,代入原式即求
$$
\sum_{i=1}^{n_{k}}f^{k}(i)=\sum_{i=1}^{2^{y}}\sum_{i+j\cdot 2^{y}\le n_{k}}f^{x}(f^{y}(i)+j\cdot 3^{y})
$$
关于后者,将$\lfloor\frac{n_{k}-i}{2^{y}}\rfloor$拆成二进制表示,进而问题即求形如$\sum_{j=0}^{2^{t}-1}f^{x}(a+j\cdot 3^{y})$
记上式为$F_{t}(a)$,转移即
$$
F_{t}(a)=\begin{cases}F_{t-1}(a)+F_{t-1}(a+2^{t-1}3^{y})&t\ge 1\\f^{x}(a)&t=0\\F_{t}(a-s\cdot 2^{x})+s\cdot 2^{t}3^{x}&s=\lfloor\frac{a}{2^{x}}\rfloor\ge 1\end{cases}
$$
状态仅有$o(2^{x}\log n)$个,预处理出来即可,时间复杂度为$o(2^{\frac{k}{2}}(k+\log n))$($k$是计算$f^{y}(i)$和$f^{x}(a)$)
结合上述两个做法,按$k\le 40$和$k>40$分类即可通过
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define K0 40 4 #define N 50 5 #define K 20 6 #define mod 998244353 7 #define ll long long 8 #define LL __int128 9 int k,x,y,ans,F[N][1<<K]; 10 ll n,mi[K+5]; 11 ll calc(int k,ll x){ 12 for(int i=0;i<k;i++)x=(3*x+1>>1); 13 return x; 14 } 15 int get_F(int t,LL a){ 16 if (a>=(1<<x)){ 17 LL s=(a>>x); 18 return (get_F(t,a-(s<<x))+(s%mod<<t)*mi[x])%mod; 19 } 20 if (F[t][a]>=0)return F[t][a]; 21 if (!t)return F[t][a]=calc(x,a)%mod; 22 return F[t][a]=(get_F(t-1,a)+get_F(t-1,a+((LL)mi[y]<<t-1)))%mod; 23 } 24 int main(){ 25 mi[0]=1; 26 for(int i=1;i<K+5;i++)mi[i]=3*mi[i-1]; 27 scanf("%lld%d",&n,&k); 28 for(int i=0;i<k;i++)n=(n<<1)/3; 29 if (k<=K0){ 30 x=(k>>1),y=k-x; 31 memset(F,-1,sizeof(F)); 32 for(int i=1;i<=(1<<y);i++){ 33 LL n0=(n-i>>y)+1,a=calc(y,i); 34 for(int t=0;t<N;t++) 35 if ((n0>>t)&1){ 36 ans=(ans+get_F(t,a))%mod; 37 a+=((LL)mi[y]<<t); 38 } 39 } 40 printf("%d\n",ans); 41 return 0; 42 } 43 if (k>K0){ 44 for(int i=1;i<=n;i++)ans=(ans+calc(k,i))%mod; 45 printf("%d\n",ans); 46 return 0; 47 } 48 }