Let $n$ be the number of digits in $x$ and $a(x)$ denote the number of times $f$ needs to be applied to $x$ for $x$ to reach $0$. Also, let $x_i$ be the $i$th (zero-indexed) digit of $x$ from the right, so that $x=x_{n-1}x_{n-2}\dots x_0$.
Subtask 1: It can be proven that $a(x)\in O(2^n)$, so just applying $f$ sequentially until $x$ reaches zero is sufficiently fast.
Full Solution: Let $S$ be the set of all non-negative integers whose digits consist solely of zeros and ones. We first note that either $x\in S$ or $f(x)\in S$, so it suffices to consider how $a(x)$ behaves for $x\in S$.
For $x\in S$, define $b(x)$ to be the (zero-indexed) rank of $x$ in $S$, which is just $b(x)=\sum_{i=0}^{n-1}x_i2^i$. Now for $x\in S$, let's try to relate $a(x)$ to $b(x)$.
So every time $b(x)$ decreases by two, $a(x)$ decreases by three. We can prove via induction that $a(x)=3\cdot (\sum_{i=1}^{n-1}x_i2^{i-1})+x_0$, which is very close to $3/2\cdot b(x)$. One way to get the remainder of $a(x)$ modulo $10^9+7$ is to first compute the remainders of $2^0, 2^1, \dots 2^{n-1}$ modulo $10^9+7$, then add the appropriate multiples of these values to the answer.
Time complexity: $O(n)$
Notes on avoiding overflow in the last two subtasks when using 32-bit integers:
Aidan Bai's C++ code:
#include "bits/extc++.h"
using namespace std;
using ll = long long;
#define sz(x) int(std::size(x))
constexpr ll mod = 1e9+7;
void solve(){
string s;
cin>>s;
ll moves=0;
int n=sz(s);
ll tpow[n]{}; // powers of 2
tpow[0]=1;
for(int i = 1; i<n; i++){
tpow[i]=(tpow[i-1]*2)%mod;
}
{
// first make all digits 0 or 1
bool all01=1;
for(auto u: s){
if(u!='0' && u!='1'){
all01=0;
break;
}
}
if(!all01){
moves++;
for(auto &u: s){
u=char(((u-'0')%2)+'0');
}
}
}
reverse(s.begin(),s.end());
for(int i = 0; i<n; i++){
if(s[i]=='1'){
if(i==0)moves++;
else{
moves=(moves+tpow[i]+tpow[i-1])%mod;
}
}
}
cout<<moves<<"\n";
}
int main(){
cin.tie(0)->sync_with_stdio(0);
cin.exceptions(ios::failbit);
int t;
cin>>t;
while(t--)solve();
}
Melody Yu's Python code:
MOD=1000000007
cost=[1]
sum=1
for i in range(1,200003):
cost.append(sum+2)
sum+=cost[i]
sum%=MOD
t=int(input())
for _ in range(t):
x=input()
if x=='0':
continue
x=x[::-1]
ans=0
cnt=0
for i in range(len(x)):
v=ord(x[i])-ord('0')
if v%2==1:
ans+=cost[i]
ans%=MOD
if v!=0 and v!=1:
cnt+=1
if cnt>0:
ans+=1
ans%=MOD
print(ans)