题目传送门
解题思路:
用一个vector维护每一个点都可以乘出哪些数来,然后将(n,m)的所有数从小到大输出即可.
要用一个bool ff[j][k]来维护当前这个点(i,j)里面有没有被放过k,以此保证vector是个集合,不然会MLE(压维也不行)
AC代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<vector> 4 #include<cstring> 5 6 using namespace std; 7 8 int n,m,k,a[101][101],ans,now; 9 vector<int> s[2][101]; 10 bool vis[101],ff[101][101]; 11 12 int main() { 13 scanf("%d%d%d",&n,&m,&k); 14 for(int i = 1;i <= n; i++) 15 for(int j = 1;j <= m; j++) 16 scanf("%d",&a[i][j]); 17 s[1][1].push_back(a[1][1]); 18 for(int i = 1;i <= n; i++,now ^= 1) 19 for(int j = 1;j <= m; j++) { 20 for(int p = 1;p <= s[now^1][j].size(); p++) { 21 int u = a[i][j] * s[now^1][j][p-1] % k; 22 if(!ff[j][u]) { 23 s[now][j].push_back(u); 24 ff[j][u] = 1; 25 } 26 } 27 s[now^1][j].clear(); 28 for(int p = 1;p <= s[now][j-1].size(); p++) { 29 int u = a[i][j] * s[now][j-1][p-1] % k; 30 if(!ff[j][u]) { 31 s[now][j].push_back(u); 32 ff[j][u] = 1; 33 } 34 } 35 memset(ff,0,sizeof(ff)); 36 } 37 for(int i = 1;i <= s[now^1][m].size(); i++) 38 if(vis[s[now^1][m][i-1] % k] == 0) 39 vis[s[now^1][m][i-1] % k] = 1,ans++; 40 printf("%d ",ans); 41 for(int i = 0;i <= k; i++) 42 if(vis[i]) 43 printf("%d ",i); 44 return 0; 45 }