洛谷 P2049 魔术棋子(vector)

题目传送门

解题思路:

用一个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\n",ans);
41     for(int i = 0;i <= k; i++)
42         if(vis[i])
43             printf("%d ",i);
44     return 0;
45 }

猜你喜欢

转载自www.cnblogs.com/lipeiyi520/p/12339864.html
今日推荐