NC221010. 同源数组(HardVersion)
描述
输入描述
第一行输入三个正整数并且保证p是一个质数。
接下来n行,每行m个整数表示第i个数组的第j个元素
输出描述
本题为spj,你可以输出任何符合题目要求的答案。
首先输出一个正整数g表示划分的同源集合数目。
接下来按照顺序输出每个集合中的数组编号。(数组从0开始编号)
输出行,首先输出一个整数,表示集合的大小,接下来输出一行若干整数,整数与整数之间空一个空格。
示例1
输入:
15 5 998244353 0 0 0 0 5 1 1 1 1 1 0 0 1 1 1 1 3 6 10 15 0 0 0 7 7 1 0 0 0 0 0 0 0 0 6 0 0 0 7 10 0 0 0 9 8 1 2 1 2 1 0 0 0 0 5 0 0 1 2 1 1 2 3 4 5 0 0 0 9 2 0 0 0 7 10086
输出:
8 4 5 1 12 3 1 9 1 2 1 11 3 4 7 14 2 13 8 2 0 10 1 6
示例2
输入:
6 8 7 4 4 6 4 0 2 1 1 4 2 0 2 1 6 4 1 4 5 5 2 6 5 5 4 4 4 6 4 0 2 1 1 4 5 5 2 6 5 5 1 4 2 0 2 1 6 4 1
输出:
1 6 0 1 2 3 4 5
C++ 解法, 执行用时: 1267ms, 内存消耗: 3256K, 提交时间: 2021-10-15 21:34:37
#pragma GCC optimize("3", "inline", "Ofast") #include<bits/stdc++.h> using namespace std; #define broken fprintf(stderr, "running on %s %d\n", __FUNCTION__, __LINE__) #define sz(a) int((a).size()) #define x first #define y second #define mp make_pair typedef long long i64; typedef unsigned long long u64; const int N = 1e2 + 10, M = 1e3 + 10, T = 1e5 + 10, V = T - 10; vector<int> a[N]; int inv[T], fac[T], ifac[T], n, m, p; map<vector<int>, vector<int> > g; void Mod(int &x) { x += x >> 31 & p; } int power(int a, int b, int c = 1) { for(; b; b >>= 1, a = 1ll * a * a % p) if(b & 1) c = 1ll * c * a % p; return c; } int C(int n, int m) {return n < m ? 0 : 1ll * fac[n] * ifac[m] % p * ifac[n - m] % p; } int binom(int n, int m) { if(n < m) return 0; if(m == 0) return 1; int res = binom(n / p, m / p); n %= p, m %= p; if(n < m) return 0; if(n <= V) return 1ll * C(n, m) * res % p; for(int i = n; i >= n - m + 1; i--) res = 1ll * res * i % p; return 1ll * res * ifac[m] % p; } void initmath(int n) { fac[0] = ifac[0] = inv[1] = 1; for(int i = 2; i <= n; i++) inv[i] = 1ll * inv[p % i] * (p - p / i) % p; for(int i = 1; i <= n; i++) { fac[i] = 1ll * fac[i - 1] * i % p; ifac[i] = 1ll * ifac[i - 1] * inv[i] % p; } return; } int main() { scanf("%d%d%d", &n, &m, &p); initmath(V); for(int i = 0; i < n; i++) { a[i].resize(m); for(int j = 0; j < m; j++) { scanf("%d", &a[i][j]); } vector<int> b(m); int pos = 0; while(pos < m && !a[i][pos]) pos++; if(pos < m - 1) { int x = 0, base = 1; b = a[i]; for(int j = 1; pos + j < m; j++) { int t = j; for(; t % p == 0; t /= p); if(t == 1) { x += 1ll * b[pos + j] * power(a[i][pos], p - 2) % p * base; base *= p; } int coef = binom(x, j); if(j & 1) coef = (p - coef) % p; for(int k = pos; k + j < m; k++) { Mod(b[k + j] += 1ll * coef * a[i][k] % p - p); } } } else { b = a[i]; } g[b].push_back(i); } printf("%d\n", sz(g)); for(auto v : g) { printf("%d\n", sz(v.y)); for(int a : v.y) printf("%d ", a); printf("\n"); } return 0; }