Problem:
Score : 800 points

Problem Statement

Given are integers N and X. For each integer k between 0 and X (inclusive), find the answer to the following question, then compute the sum of all those answers, modulo 998244353.

Let us repeat the following operation on the integer k. Operation: if the integer is currently odd, subtract 1 from it and divide it by 2; otherwise, divide it by 2 and add 2^{N-1} to it. How many operations need to be performed until k returns to its original value? (The answer is considered to be 0 if k never returns to its original value.)

Constraints

1 \leq N \leq 2\times 10^5

0 \leq X < 2^N

X is given in binary and has exactly N digits. (In case X has less than N digits, it is given with leading zeroes.)

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
X

Output

Print the sum of the answers to the questions for the integers between 0 and X (inclusive), modulo 998244353.

Sample Input 1

3
111

Sample Output 1

40

For example, for k=3, the operation changes k as follows: 1,0,4,6,7,3. Therefore the answer for k=3 is 6.

Sample Input 2

6
110101

Sample Output 2

616

Sample Input 3

30
001110011011011101010111011100

Sample Output 3

549320998

Solution in C++14 (Clang 3.8.0) (judge verdict: Accepted)

#include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstring>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <cstdint>
using namespace std;
typedef long long ll;
#define MP make_pair
#define PB push_back
#define inf 1000000007
#define mod 998244353
#define rep(i,n) for(int i = 0; i < (int)(n); ++i)
#define int long long
vector<vector<int> > dev;

signed main(){
    int n;
    string s;
    cin >> n >> s;
    vector<int>t(n);
    // int k =0;
    // int qq = 1;
    rep(i,n){
        t[i] = s[i]-'0';
    }
    // rep(i,n){
    //     k += qq*t[n-1-i]%mod;
    //     k %= mod;
    //     qq*=2;
    //     qq%= mod;
    // }
    // cerr << k << endl;
    int mx = 0;
    dev.resize(n+1);
    for(int i=1;i<=n;i++){
        for(int j=i;j<=n;j+=i){
            dev[j].push_back(i);
        }
    }
    vector<int> res(n+1);
    vector<int> p;
    for(auto x:dev[n]){
        if(x%2==0)continue;
        int len = n/x;
        p.push_back(len);
        vector<vector<bool> > ichi(len,vector<bool>(2));
        vector<vector<int> > dai(len,vector<int>(2,-1));
        vector<vector<int> > sho(len,vector<int>(2,-1));
        rep(cc,len){
            rep(i,2){
                bool ichiflag = 1;
                rep(j,n/len){
                    int id = len*j+cc;
                    if(j%2==0){
                        int k = i;  
                        if(t[id]!=k){
                            ichiflag = 0;
                            break;
                        }
                    }else{
                        int k = 1-i;
                        if(t[id]!=k){
                            ichiflag = 0;
                            break;
                        }
                    }
                }
                ichi[cc][i] = ichiflag;
            }
        }
        rep(cc,len){
            rep(i,2){
                rep(j,n/len){
                    int id = len*j+cc;
                    if(j%2==0){
                        int k = i;  
                        if(t[id]<k){
                            dai[cc][i] = j;
                            break;
                        }else if(t[id]>k){
                            dai[cc][i] = -1;
                            break;
                        }
                    }else{
                        int k = 1-i;
                        if(t[id]<k){
                            dai[cc][i] = j;
                            break;
                        }else if(t[id]>k){
                            dai[cc][i] = -1;
                            break;
                        }
                    }
                }
            }
        }
        rep(cc,len){
            rep(i,2){
                rep(j,n/len){
                    int id = len*j+cc;
                    if(j%2==0){
                        int k = i;  
                        if(t[id]>k){
                            sho[cc][i] = j;
                            break;
                        }else if(t[id]<k){
                            sho[cc][i] = -1;
                            break;
                        }
                    }else{
                        int k = 1-i;
                        if(t[id]>k){
                            sho[cc][i] = j;
                            break;
                        }else if(t[id]<k){
                            sho[cc][i] = -1;
                            break;
                        }
                    }
                }
            }
        }
        int block = n/len;
        vector<vector<vector<int> > > dp(len,vector<vector<int>>(block+1,vector<int>(2,0)));
        rep(i,len){
            if(i==0){
                if(ichi[i][0]){
                    dp[i][block][1] +=1;
                }else if(dai[i][0]!=-1){
                    dp[i][dai[i][0]][1] += 1;
                }else if(sho[i][0]!=-1){
                    dp[i][sho[i][0]][0] += 1;
                }
                if(ichi[i][1]){
                    dp[i][block][1] +=1;
                }else if(dai[i][1]!=-1){
                    dp[i][dai[i][1]][1] += 1;
                }else if(sho[i][1]!=-1){
                    dp[i][sho[i][1]][0] += 1;
                }
            }else{
                if(ichi[i][0]){
                    rep(j,block+1){
                        dp[i][j][1] += dp[i-1][j][1];
                        dp[i][j][1] %= mod;
                        dp[i][j][0] += dp[i-1][j][0];
                        dp[i][j][0] %= mod;
                    }
                }else if(dai[i][0]!=-1){
                    for(int j=0;j<=dai[i][0];j++){
                        dp[i][j][1] += dp[i-1][j][1];
                        dp[i][j][1] %= mod;
                        dp[i][j][0] += dp[i-1][j][0];
                        dp[i][j][0] %= mod;
                    }
                    for(int j=dai[i][0]+1;j<=block;j++){
                        dp[i][dai[i][0]][1] += (dp[i-1][j][1] + dp[i-1][j][0])%mod;
                        dp[i][dai[i][0]][1] %= mod;
                    }
                }else if(sho[i][0]!=-1){
                    for(int j=0;j<=sho[i][0];j++){
                        dp[i][j][1] += dp[i-1][j][1];
                        dp[i][j][1] %= mod;
                        dp[i][j][0] += dp[i-1][j][0];
                        dp[i][j][0] %= mod;
                    }
                    for(int j=sho[i][0]+1;j<=block;j++){
                        dp[i][sho[i][0]][0] += (dp[i-1][j][1] + dp[i-1][j][0])%mod;
                        dp[i][sho[i][0]][0] %= mod;
                    }
                }
                if(ichi[i][1]){
                    rep(j,block+1){
                        dp[i][j][1] += dp[i-1][j][1];
                        dp[i][j][1] %= mod;
                        dp[i][j][0] += dp[i-1][j][0];
                        dp[i][j][0] %= mod;
                    }
                }else if(dai[i][1]!=-1){
                    for(int j=0;j<=dai[i][1];j++){
                        dp[i][j][1] += dp[i-1][j][1];
                        dp[i][j][1] %= mod;
                        dp[i][j][0] += dp[i-1][j][0];
                        dp[i][j][0] %= mod;
                    }
                    for(int j=dai[i][1]+1;j<=block;j++){
                        dp[i][dai[i][1]][1] += (dp[i-1][j][1] + dp[i-1][j][0])%mod;
                        dp[i][dai[i][1]][1] %= mod;
                    }
                }else if(sho[i][1]!=-1){
                    for(int j=0;j<=sho[i][1];j++){
                        dp[i][j][1] += dp[i-1][j][1];
                        dp[i][j][1] %= mod;
                        dp[i][j][0] += dp[i-1][j][0];
                        dp[i][j][0] %= mod;
                    }
                    for(int j=sho[i][1]+1;j<=block;j++){
                        dp[i][sho[i][1]][0] += (dp[i-1][j][1] + dp[i-1][j][0])%mod;
                        dp[i][sho[i][1]][0] %= mod;
                    }
                }
            }
        }
        rep(i,block){
            res[len] += dp[len-1][i][0];
            res[len] %= mod;    
        }
        res[len] += dp[len-1][block][1];
        res[len] %= mod;
    }
    int ccc = 0;
    sort(p.begin(),p.end());
    for(auto x:p){
        //cerr << x << " " << res[x] << endl;
        for(auto y:dev[x]){
            if(y==x)continue;
            res[x] += (mod-res[y])%mod;
            res[x] %= mod;
        }
        //cerr << x << " " << res[x] << endl;
        ccc += res[x];
        ccc %= mod;
    }
    //cerr << ccc << endl;
    int ans = 0;
    for(auto x:p){
        ans += x*2%mod*res[x]%mod;
        ans %= mod;
    }
    cout << ans << endl;
    return 0;
}