Problem:
Score : 1400 points

Problem Statement

Consider the following set of rules for encoding strings consisting of 0 and 1:

Strings 0 and 1 can be encoded as 0 and 1, respectively.

If strings A and B can be encoded as P and Q, respectively, then string AB can be encoded as PQ.

If string A can be encoded as P and K \geq 2 is a positive integer, then string AA...A (A repeated K times) can be encoded as (PxK).

For example, string 001001001, among other possibilities, can be encoded as 001001001, 00(1(0x2)x2)1 and (001x3).

Let's call string A a subset of string B if:

A and B are equal in length and consist of 0 and 1;

for all indices i such that A_i = 1, it's also true that B_i = 1.

You are given string S consisting of 0 and 1. Find the total number of distinct encodings of all subsets of S, modulo 998244353.

Constraints

1 \leq |S| \leq 100

S consists of 0 and 1.

Input

Input is given from Standard Input in the following format:

S

Output

Print the total number of distinct encodings of all subsets of S modulo 998244353.

Sample Input 1

011

Sample Output 1

9

There are four subsets of S:

011 can be encoded as 011 and 0(1x2);

010 can be encoded as 010;

001 can be encoded as 001 and (0x2)1;

000 can be encoded as 000, 0(0x2), (0x2)0 and (0x3).

Thus, the total number of encodings of all subsets of S is 2 + 1 + 2 + 4 = 9.

Sample Input 2

0000

Sample Output 2

10

This time S has only one subset, but it can be encoded in 10 different ways.

Sample Input 3

101110

Sample Output 3

156

Sample Input 4

001110111010110001100000100111

Sample Output 4

363383189

Don't forget to take the result modulo 998244353.

Solution in Java8 (OpenJDK 1.8.0) (judge verdict: Time Limit Exceeded)

import java.util.Arrays;
import java.util.Scanner;

public class Main {
  static Scanner sc = new Scanner(System.in);
  static long MOD = 998244353;

  public static void main(String[] args) {
    char[] s = sc.next().toCharArray();
    int N = s.length;
    boolean[] S = new boolean[N];
    for (int i = 0; i < N; i++) {
      S[i] = s[i] == '1';
    }
    System.out.println(solve(S));
  }

  static long solve(boolean[] s) {
    int N = s.length;
    long[][] count = new long[N][N];
    for (int i = 0; i < N; i++) {
      for (int j = i + 1; j < N; j++) {
        boolean[] cs = new boolean[j - i + 1];
        for (int k = i; k <= j; k++) {
          cs[k - i] = s[k];
        }
        count[i][j] = count(cs);
      }
    }
//    for (int i = 0; i < N; i++) {
//      for (int j = i + 1; j < N; j++) {
//        System.err.println("i:" + i + " j:" + j + " " + count[i][j]);
//      }
//    }
//    System.err.println("");
    long[] dp = new long[N + 1];
    dp[0] = 1;
    for (int i = 0; i < N; i++) {
      dp[i] %= MOD;
      if (s[i]) {
        dp[i + 1] += dp[i] * 2;
      } else {
        dp[i + 1] += dp[i];
      }
      for (int j = i; j < N; j++) {
        dp[j + 1] += dp[i] * count[i][j] % MOD;
      }
//      System.err.println(Arrays.toString(dp));
    }
    return dp[N] % MOD;
  }

  static long count(boolean[] s) {
    long ret = 0;
    for (int i = 2; i <= s.length; i++) {
      if (s.length % i != 0) continue;
      boolean[] sub = new boolean[s.length / i];
      Arrays.fill(sub, true);
      for (int j = 0; j < s.length; j++) {
        sub[j % sub.length] &= s[j];
      }
      ret += solve(sub);
      if (ret >= MOD) ret -= MOD;
    }
    return ret;
  }
}