#include<bits/stdc++.h>usingnamespacestd;constexprintP=998244353;usingMint=MInt<P>;intsolve(string&a,string&b){intn=a.length();vector<Mint>dp(n+1),A(n+1),B(n+1);// dp[i] is the expected moves when there are i mismatches b/w the strings.
// Every dp[i] would be a linear function of the form Ax + B.
// Let's maintain 2 arrays A and B to store this linear function.
A[0]=0,B[0]=0;// 0*x + 0
A[1]=1,B[1]=0;// 1*x + 0
for(inti=1;i<n;i++){// dp[i] = 1 + (1 - p)*dp[i - 1] + p*dp[i + 1]
// p*dp[i + 1] = dp[i] - (1 - p)*dp[i - 1] - 1;
// p is the probability of picking up matched entry.
//
// p = (n - i)/n
// p will never be zero, so we can divide freely.
Mintp=(Mint)(n-i)/n;Mintdenom_inv=1/p;A[i+1]=denom_inv*(A[i]-(1-p)*A[i-1]);B[i+1]=denom_inv*(B[i]-(1-p)*B[i-1]-1);}// Now, dp[n] would be populated as a linear function.
// However, there's a different way to populate dp[n].
// dp[n] = 1 + dp[n - 1]
// Hence, both these value should be equal.
//
// Ex + F = 1 + Px + Q
// x = (1 + Q - F)/(E - P)
Mintx=(1+B[n-1]-B[n])/(A[n]-A[n-1]);for(inti=0;i<=n;i++){dp[i]=A[i]*x+B[i];}intmismatch_count=0;for(inti=0;i<n;i++){if(a[i]!=b[i]){mismatch_count++;}}returndp[mismatch_count].val();}intmain(){intt;cin>>t;for(intzz=0;zz<t;zz++){intn;cin>>n;stringa,b;cin>>a>>b;cout<<solve(a,b)<<"\n";}return0;}
#include<bits/stdc++.h>usingnamespacestd;usingi64=longlong;template<classT>constexprTpower(Ta,i64b){Tres=1;for(;b;b/=2,a*=a){if(b%2){res*=a;}}returnres;}constexpri64mul(i64a,i64b,i64p){i64res=a*b-i64(1.L*a*b/p)*p;res%=p;if(res<0){res+=p;}returnres;}template<i64P>structMLong{i64x;constexprMLong():x{}{}constexprMLong(i64x):x{norm(x%getMod())}{}statici64Mod;constexprstatici64getMod(){if(P>0){returnP;}else{returnMod;}}constexprstaticvoidsetMod(i64Mod_){Mod=Mod_;}constexpri64norm(i64x)const{if(x<0){x+=getMod();}if(x>=getMod()){x-=getMod();}returnx;}constexpri64val()const{returnx;}explicitconstexproperatori64()const{returnx;}constexprMLongoperator-()const{MLongres;res.x=norm(getMod()-x);returnres;}constexprMLonginv()const{assert(x!=0);returnpower(*this,getMod()-2);}constexprMLong&operator*=(MLongrhs)&{x=mul(x,rhs.x,getMod());return*this;}constexprMLong&operator+=(MLongrhs)&{x=norm(x+rhs.x);return*this;}constexprMLong&operator-=(MLongrhs)&{x=norm(x-rhs.x);return*this;}constexprMLong&operator/=(MLongrhs)&{return*this*=rhs.inv();}friendconstexprMLongoperator*(MLonglhs,MLongrhs){MLongres=lhs;res*=rhs;returnres;}friendconstexprMLongoperator+(MLonglhs,MLongrhs){MLongres=lhs;res+=rhs;returnres;}friendconstexprMLongoperator-(MLonglhs,MLongrhs){MLongres=lhs;res-=rhs;returnres;}friendconstexprMLongoperator/(MLonglhs,MLongrhs){MLongres=lhs;res/=rhs;returnres;}friendconstexprstd::istream&operator>>(std::istream&is,MLong&a){i64v;is>>v;a=MLong(v);returnis;}friendconstexprstd::ostream&operator<<(std::ostream&os,constMLong&a){returnos<<a.val();}friendconstexprbooloperator==(MLonglhs,MLongrhs){returnlhs.val()==rhs.val();}friendconstexprbooloperator!=(MLonglhs,MLongrhs){returnlhs.val()!=rhs.val();}};template<>i64MLong<0LL>::Mod=i64(1E18)+9;template<intP>structMInt{intx;constexprMInt():x{}{}constexprMInt(i64x):x{norm(x%getMod())}{}staticintMod;constexprstaticintgetMod(){if(P>0){returnP;}else{returnMod;}}constexprstaticvoidsetMod(intMod_){Mod=Mod_;}constexprintnorm(intx)const{if(x<0){x+=getMod();}if(x>=getMod()){x-=getMod();}returnx;}constexprintval()const{returnx;}explicitconstexproperatorint()const{returnx;}constexprMIntoperator-()const{MIntres;res.x=norm(getMod()-x);returnres;}constexprMIntinv()const{assert(x!=0);returnpower(*this,getMod()-2);}constexprMInt&operator*=(MIntrhs)&{x=1LL*x*rhs.x%getMod();return*this;}constexprMInt&operator+=(MIntrhs)&{x=norm(x+rhs.x);return*this;}constexprMInt&operator-=(MIntrhs)&{x=norm(x-rhs.x);return*this;}constexprMInt&operator/=(MIntrhs)&{return*this*=rhs.inv();}friendconstexprMIntoperator*(MIntlhs,MIntrhs){MIntres=lhs;res*=rhs;returnres;}friendconstexprMIntoperator+(MIntlhs,MIntrhs){MIntres=lhs;res+=rhs;returnres;}friendconstexprMIntoperator-(MIntlhs,MIntrhs){MIntres=lhs;res-=rhs;returnres;}friendconstexprMIntoperator/(MIntlhs,MIntrhs){MIntres=lhs;res/=rhs;returnres;}friendconstexprstd::istream&operator>>(std::istream&is,MInt&a){i64v;is>>v;a=MInt(v);returnis;}friendconstexprstd::ostream&operator<<(std::ostream&os,constMInt&a){returnos<<a.val();}friendconstexprbooloperator==(MIntlhs,MIntrhs){returnlhs.val()==rhs.val();}friendconstexprbooloperator!=(MIntlhs,MIntrhs){returnlhs.val()!=rhs.val();}};template<>intMInt<0>::Mod=998244353;template<intV,intP>constexprMInt<P>CInv=MInt<P>(V).inv();constexprintP=998244353;usingMint=MInt<P>;intsolve(string&a,string&b){intn=a.length();vector<Mint>dp(n+1),A(n+1),B(n+1);// dp[i] is the expected moves when there are i mismatches b/w the strings.
// Every dp[i] would be a linear function of the form Ax + B.
// Let's maintain 2 arrays A and B to store this linear function.
A[0]=0,B[0]=0;// 0*x + 0
A[1]=1,B[1]=0;// 1*x + 0
for(inti=1;i<n;i++){// dp[i] = 1 + (1 - p)*dp[i - 1] + p*dp[i + 1]
// p*dp[i + 1] = dp[i] - (1 - p)*dp[i - 1] - 1;
// p is the probability of picking up matched entry.
//
// p = (n - i)/n
// p will never be zero, so we can divide freely.
Mintp=(Mint)(n-i)/n;Mintdenom_inv=1/p;A[i+1]=denom_inv*(A[i]-(1-p)*A[i-1]);B[i+1]=denom_inv*(B[i]-(1-p)*B[i-1]-1);}// Now, dp[n] would be populated as a linear function.
// However, there's a different way to populate dp[n].
// dp[n] = 1 + dp[n - 1]
// Hence, both these value should be equal.
//
// Ex + F = 1 + Px + Q
// x = (1 + Q - F)/(E - P)
Mintx=(1+B[n-1]-B[n])/(A[n]-A[n-1]);for(inti=0;i<=n;i++){dp[i]=A[i]*x+B[i];}intmismatch_count=0;for(inti=0;i<n;i++){if(a[i]!=b[i]){mismatch_count++;}}returndp[mismatch_count].val();}intmain(){intt;cin>>t;for(intzz=0;zz<t;zz++){intn;cin>>n;stringa,b;cin>>a>>b;cout<<solve(a,b)<<"\n";}return0;}