dp[ どれを使ったか ][ これまでの余り ]
int divS(string s, int K) { vector<int> v; for (int i = 0; i < s.size(); ++i) { v.push_back(s[i] - '0'); } for (int i = 0; i + 1 < v.size(); ++i) { v[i + 1] += (v[i] % K) * 10; } return v.back() % K; } lli gcd(lli a, lli b) { return b ? gcd(b, a % b) : a; } class WickedTeacher { public: string cheatProbability(vector <string> ns, int K) { const int N = 15 + 1; const int BIT = 1 << N; const int M = 101; char buff[1000]; int D[N][M]; for (int i = 0; i < ns.size(); ++i) { for (int j = 0; j < K; ++j) { sprintf(buff, "%d", j); string t = string(buff) + ns[i]; D[i][j] = divS(t, K); } } static lli dp[BIT][M]; fill(&dp[0][0], &dp[BIT][0], 0); dp[0][0]= 1; for (int bit = 0; bit < (1 << ns.size()); ++bit) { for (int m = 0; m < M; ++m) { if (dp[bit][m] == 0) continue; for (int i = 0; i < ns.size(); ++i) { if (bit & (1 << i)) continue; dp[bit | (1 << i)][D[i][m]] += dp[bit][m]; } } } lli q = 0; lli p = dp[(1 << ns.size()) - 1][0]; for (int m = 0; m < K; ++m) { q += dp[(1 << ns.size()) - 1][m]; } if (p == 0 && q == 0) return "0/0"; lli r = gcd(max(p, q), min(p, q)); p /= r; q /= r; string P, Q; sprintf(buff, "%lld", p); P = string(buff); sprintf(buff, "%lld", q); Q = string(buff); return P + "/" + Q; } };