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 Rust (1.42.0) (judge verdict: Accepted)

use proconio::input;

#[allow(unused_imports)]
use proconio::marker::{Bytes, Chars, Usize1};
#[allow(unused_imports)]
use std::cmp::*;
#[allow(unused_imports)]
use std::collections::*;
#[allow(unused_imports)]
use std::ops::*;
#[derive(Clone, Debug, Default)]
struct Struct;

//
// ModInt
//

const M: i64 = 998244353;
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct ModInt {
    val: i64,
}
const M0: ModInt = ModInt { val: 0 };
const M1: ModInt = ModInt { val: 1 };
//const M_ERROR: ModInt = ModInt { val: -1 };

impl ModInt {
    fn new(v: i64) -> ModInt {
        ModInt {
            val: ModInt::val_from_i64(v),
        }
    }
    fn val_from_i64(v: i64) -> i64 {
        let t = v % M;
        if t < 0 {
            t + M
        } else {
            t
        }
    }
    fn val_from_addval(t: i64) -> i64 {
        if t >= M {
            t - M
        } else {
            t
        }
    }

    fn pow(self, exp: i64) -> ModInt {
        if exp == 0 {
            M1
        } else {
            let x = self.pow(exp / 2);
            if exp % 2 == 0 {
                x * x
            } else {
                self * x * x
            }
        }
    }

    fn inv(self) -> ModInt {
        self.pow(M - 2)
    }
}

impl std::ops::Add for ModInt {
    type Output = ModInt;
    fn add(self, rhs: ModInt) -> ModInt {
        ModInt {
            val: ModInt::val_from_addval(self.val + rhs.val),
        }
    }
}
impl std::ops::Add<i64> for ModInt {
    type Output = ModInt;
    fn add(self, rhs: i64) -> ModInt {
        ModInt {
            val: ModInt::val_from_i64(self.val + rhs),
        }
    }
}
impl std::ops::AddAssign for ModInt {
    fn add_assign(&mut self, other: ModInt) {
        self.val = ModInt::val_from_addval(self.val + other.val);
    }
}
impl std::ops::AddAssign<i64> for ModInt {
    fn add_assign(&mut self, other: i64) {
        self.val = ModInt::val_from_i64(self.val + other);
    }
}

impl std::ops::Sub for ModInt {
    type Output = ModInt;
    fn sub(self, rhs: ModInt) -> ModInt {
        ModInt {
            val: ModInt::val_from_addval(self.val - rhs.val + M)
        }
    }
}
impl std::ops::Sub<i64> for ModInt {
    type Output = ModInt;
    fn sub(self, rhs: i64) -> ModInt {
        self - ModInt::new(rhs)
    }
}
impl std::ops::SubAssign for ModInt {
    fn sub_assign(&mut self, other: ModInt) {
        self.val = ModInt::val_from_addval(self.val - other.val + M);
    }
}
impl std::ops::SubAssign<i64> for ModInt {
    fn sub_assign(&mut self, other: i64) {
        self.val = ModInt::val_from_i64(self.val - other);
    }
}

impl std::ops::Neg for ModInt {
    type Output = ModInt;
    fn neg(self) -> ModInt {
        ModInt {
            val: if self.val == 0 { 0 } else { M - self.val },
        }
    }
}

impl std::ops::Mul for ModInt {
    type Output = ModInt;
    fn mul(self, rhs: ModInt) -> ModInt {
        ModInt {
            val: self.val * rhs.val % M,
        }
    }
}
impl std::ops::Mul<i64> for ModInt {
    type Output = ModInt;
    fn mul(self, rhs: i64) -> ModInt {
        self * ModInt::new(rhs)
    }
}

impl std::ops::Div for ModInt {
    type Output = ModInt;
    fn div(self, rhs: ModInt) -> ModInt {
        self * rhs.inv()
    }
}
impl std::ops::Div<i64> for ModInt {
    type Output = ModInt;
    fn div(self, rhs: i64) -> ModInt {
        self / ModInt::new(rhs)
    }
}

impl std::fmt::Display for ModInt {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.val)
    }
}

//#[proconio::fastout]
fn main() {
    input! {
        n: usize,
        mut s:Bytes,
    }

    // 右ローテートして最上位を反転
    // N回繰り返すと元の値を全ビット反転したものになる
    // pattern !pattern pattern !pattern ... pattern の形 で 周期T=|pattern|*2
    // T = N÷奇数

    /*
        X = 100110...
        (prefix,T) -> パターン数を計算する

              prefix  0     1000     10010    ...
        T/2=1         0     -        -
        T/2=2         0x    -        -
        T/2=3         0xx   100      -
        T/2=4         0xxx  1000     -
        ...
        みたいな表を作る

    */
    let mut pow2 = Vec::with_capacity(n + 1);
    let mut x = M1;
    for _i in 0..=n {
        pow2.push(x);
        x = x + x;
    }
    let mut pat_lens = Vec::new();
    let mut counts = Vec::new();

    for pat_len in 1..=n {
        if n % pat_len == 0 && (n / pat_len) % 2 == 1 {
            let mut j = 0;
            let mut b = 0;
            let mut count = M0;
            for i in 0..n {
                // この時点で[0..i-1] がパターンに一致することは確認済みとする。
                if s[i] == b'1' {
                    s[i] = b'0';
                    // [0..i] がパターンに一致するなら、何パターンあるかを調べる
                    if i >= pat_len {
                        if s[i] == s[j] ^ b {
                            count += 1;
                        }
                    } else {
                        count += pow2[pat_len - (i + 1)];
                    }
                    s[i] = b'1';
                }

                // [0..i] が一致するかどうかを調べる
                if i >= pat_len {
                    if s[i] != s[j] ^ b {
                        break;
                    }
                }

                // ちょうどXの値で一致したら +1パターン
                if i == n - 1 {
                    count += 1;
                }

                // (b,j)++
                j += 1;
                if j == pat_len {
                    j = 0;
                    b = 1 - b;
                }
            }
            pat_lens.push(pat_len);
            counts.push(count);
        }
    }

    let l = pat_lens.len();
    //for i in 0..l {
    //    println!("pat_len={} count={} sum={}", pat_lens[i], counts[i], counts[i]*(pat_lens[i] as i64)*2);
    //}

    // 重複してカウントしたものを除く
    for i in 0..l {
        let pat_len = pat_lens[i];
        let count = counts[i];

        for j in i+1 .. l {
            if pat_lens[j] % pat_len == 0 && (pat_lens[j] / pat_len) % 2 == 1 {
                counts[j] -= count;
            }
        }
    }

    let mut ans = M0;
    for i in 0..l {
        ans += counts[i]*(pat_lens[i] as i64)*2;
    }
    println!("{}", ans);
}