Problem:
Teaching Assistant
問題
$N$ 人の学生がある講義のレポートを提出しました。この講義のTAであるYoika君は、$N$ 人全員のレポートの長さが同じであることに違和感を感じたため、提出されたレポートを確認し、不正が行われていないかどうかチェックすることにしました。
学生 $A$ と学生 $B$ のレポートを表す文字列において、異なる文字の個数が $1$ 以下のとき、不正が行われたと見なします。
より厳密には、以下の条件を満たすとき、学生 $A$ を不正行為者と見なします。
<条件>
ある学生 $B$ ($A \neq B$) が存在し、$S_i \neq T_i$ を満たす $i$ ($1 \leq i \leq |S|$) の個数が $1$ 以下 (学生 $A$ のレポートの $i$ 文字目を $S_i$ 、学生 $B$ のレポートの $j$ 文字目を $T_j$ とする)
各学生のレポートを表す文字列 $\mathrm{report}_k$ ($1 \leq k \leq N$) が与えられるので、不正を行ったと見なされる学生の人数を求めてください。
制約
$1 \leq N \leq 100$
$3 \leq |\mathrm{report}_k| \leq 100$
各文字列は英小文字で構成され、その長さはすべて等しい
入力
入力は以下の形式で標準入力から与えられます。
$N$
$\mathrm{report}_{1}$
$\mathrm{report}_{2}$
$\vdots$
$\mathrm{report}_{N}$
出力
不正を行ったと見なされる学生の人数を出力してください。
入力例 1
3
osaka
okaka
okura
出力例 1
2
$1$ 人目の文字列
osaka
と $2$ 人目の文字列
okaka
において、異なる文字の個数は $1$ ($2$ 文字目のみ)。
$1$ 人目の文字列
osaka
と $3$ 人目の文字列
okura
において、異なる文字の個数は $3$ ($2$ 文字目、$3$ 文字目、$4$ 文字目)。
$2$ 人目の文字列
okaka
と $1$ 人目の文字列
osaka
において、異なる文字の個数は $1$ ($2$ 文字目のみ)。
$2$ 人目の文字列
okaka
と $3$ 人目の文字列
okura
において、異なる文字の個数は $2$ ($3$ 文字目、$4$ 文字目)。
$3$ 人目の文字列
okura
と $1$ 人目の文字列
osaka
において、異なる文字の個数は $3$ ($2$ 文字目、$3$ 文字目、$4$ 文字目)。
$3$ 人目の文字列
okura
と $2$ 人目の文字列
okaka
において、異なる文字の個数は $2$ ($3$ 文字目、$4$ 文字目)。
よって、不正を行ったと見なされる学生の人数は、$1$ 人目と $2$ 人目の $2$ 人です。
入力例 2
4
osaka
suita
ichou
saito
出力例 2
0
不正を行ったと見なされる学生がいない場合も考えられます。

Submitted solutions:

code_snippet: #include "bits/stdc++.h"
using namespace std;
int main()
{
  int n;
  cin >> n;
  vector<string> report;
  for (int i = 0; i < n; ++i)
  {
    string s;
    cin >> s;
    report.push_back(s);
  }

  const long long mod[2] = {998244353, 10000000007};

  vector<long long> pow_of_26[2];
  pow_of_26[0].push_back(1);
  pow_of_26[1].push_back(1);
  for (int i = 1; i < report[0].length(); ++i)
  {
    pow_of_26[0].push_back(pow_of_26[0].back() * 26LL % mod[0]);
    pow_of_26[1].push_back(pow_of_26[1].back() * 26LL % mod[1]);
  }

  vector<long long> hash_report[2];
  unordered_map<long long, long long> hash_count[2];
  for (int i = 0; i < report.size(); ++i)
  {
    long long cur_hash[2] = {};
    for (int q = 0; q < report[i].size(); ++q)
    {
      for (int j = 0; j < 2; ++j)
      {
        cur_hash[j] += pow_of_26[j][q] * (long long)(report[i][q] - 'a');
        cur_hash[j] %= mod[j];
      }
    }
    hash_report[0].push_back(cur_hash[0]);
    hash_report[1].push_back(cur_hash[1]);
    hash_count[0][cur_hash[0]]++;
    hash_count[1][cur_hash[1]]++;
  }

  int answer = 0;
  for (int i = 0; i < report.size(); ++i)
  {
    hash_count[0][hash_report[0][i]]--;
    hash_count[1][hash_report[1][i]]--;
    bool is_cheated = false;
    for (int q = 0; q < report[i].size(); ++q)
    {
      for (int change_char = 0; change_char < 26; ++change_char)
      {
        bool possible_to_cheat = true;
        for (int j = 0; j < 2; ++j)
        {
          long long cur_hash = hash_report[j][i];
          cur_hash += mod[j] - (pow_of_26[j][q] * (long long)(report[i][q] - 'a') % mod[j]);
          cur_hash += pow_of_26[j][q] * (long long)change_char;
          cur_hash %= mod[j];
          if (hash_count[j].count(cur_hash) == 0 or hash_count[j][cur_hash] == 0)
          {
            possible_to_cheat = false;
            break;
          }
        }
        if (possible_to_cheat)
        {
          is_cheated = true;
        }
      }
    }
    hash_count[0][hash_report[0][i]]++;
    hash_count[1][hash_report[1][i]]++;
    if (is_cheated)
      answer++;
  }
  cout << answer << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 3480
final_rank: 2

code_snippet: #include <iostream>
#include <algorithm>
using namespace std;

const long long mod = 998244353;
long long N, M, A[2009];
long long dp[2009][2009], ru[2009][2009];

int main() {
	// 入力
	cin >> N >> M;
	for (int i = 1; i <= M; i++) cin >> A[i];

	// 動的計画法（初期化）
	dp[0][0] = 0;
	for (int i = 1; i <= N + 1; i++) ru[0][i] = 1;

	// 動的計画法
	for (int i = 1; i <= M; i++) {
		for (int j = 0; j <= N; j++) {
			int cl = max(0, j - (int)A[i]), cr = j + 1;
			dp[i][j] = (ru[i - 1][cr] - ru[i - 1][cl] + mod) % mod;
			ru[i][j + 1] = (ru[i][j] + dp[i][j]) % mod;
		}
	}

	// 答えを求める
	long long Answer = dp[M][N];
	for (int i = 1; i <= N; i++) { Answer *= i; Answer %= mod; }
	cout << Answer << endl;
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 64764
final_rank: 3

code_snippet: #include <bits/stdc++.h>
#define REP(i, n) for(int i = 0; i < (int)(n); i++)
using namespace std;
using ll = long long;
constexpr ll MOD = 998244353;

int main(void) {
    int n, m; cin >> n >> m;
    vector<int> a(m);
    REP(i, m) cin >> a[i];
    vector<ll> dp(n+1); //i個確保済み
    dp[0] = 1;
    REP(i, n) dp[0] = dp[0] * (i+1) % MOD;
    REP(i, m) {
        vector<ll> imos(n+1);
        REP(j, n+1) { // i色塗った時点でj個塗ってた
            imos[j] = (imos[j] + dp[j]) % MOD;
            if(j+a[i]+1 <= n) imos[j+a[i]+1] = (imos[j+a[i]+1] + MOD - dp[j]) % MOD;
        }
        REP(j, n) imos[j+1] = (imos[j] + imos[j+1]) % MOD;
        dp = imos;
    }
    cout << dp[n] << '\n';
}
accuracy: 1
time_ms: 10
memory_kb: 3472
final_rank: 1

code_snippet: #include <bits/stdc++.h>
#define REP(i, n) for(int i = 0; i < (int)(n); i++)
using namespace std;
using ll = long long;
constexpr ll MOD = 998244353;

int main(void) {
    int n, m; cin >> n >> m;
    vector<int> a(m);
    REP(i, m) cin >> a[i];
    vector<ll> dp(n+1); //i個確保済み
    dp[0] = 1;
    REP(i, n) dp[0] = dp[0] * (i+1) % MOD;
    REP(i, m) {
        vector<ll> nxt(n+1);
        REP(j, n+1) { // i色塗った時点でj個塗ってた
            for(int k = j; k <= min(n, j+a[i]); k++) {
                nxt[k] = (nxt[k] + dp[j]) % MOD;
            }
        }
        dp = nxt;
    }
    cout << dp[n] << '\n';
}
accuracy: 1
time_ms: 1640
memory_kb: 3476
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;

long long dp[5002][5002];

int main()
{
	const int mod = 998244353;

	int n, m;
	cin >> n >> m;

	dp[0][n] = 1;
	for (int i = 1; i <= n;++i){
		dp[0][n] *= i;
		dp[0][n] %= mod;
	}
	for (int i = 0; i < m; ++i)
	{
		int a;
		cin >> a;
		for (int q = 0; q <= n; ++q)
		{
			dp[i + 1][q] += dp[i][q];
			dp[i + 1][q] %= mod;
			if (q - a - 1 >= 0)
			{
				dp[i + 1][q - a - 1] += (mod - dp[i][q]);
				dp[i + 1][q - a - 1] %= mod;
			}
		}
		for (int q = n; q >= 1; --q)
		{
			dp[i + 1][q - 1] += dp[i + 1][q];
			dp[i + 1][q - 1] %= mod;
		}
	}
	cout << dp[m][0] << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 77960
final_rank: 4