原题链接:https://codeforces.com/contest/1941/problem/D
这道题vp的时候脑子瓦特了,没写出来,气死了喵~
题意是有n个man围成一个圈圈,编号从1到n顺时针排列最开始球在编号为x的小朋友手里。然后球会经过m次传递,每次传递都有要输入一个距离和方向(可能是顺时针、逆时针,或者不确定喵~)。最后,我们需要找出球可能落在哪些man手里。
所以这题可以用dp写,我们把每次传球看成一个状态,即顺时针,逆时针,或者两者均可,然后通过状态转移方程来判断最后哪些位置可以达到(一开始想的是把到一个问号前的转动数值和作为一个状态存储,结果发现想复杂了喵~~~)
对于每次传递,我们根据传递的距离r和方向c来更新球可能的位置。
如果方向是顺时针(c == '0'),球会从当前位置 j 传递到 (j + r) % n。
如果方向是逆时针(c == '1'),球会传递到 (j - r + n) % n(+n为了避免负数)。
如果方向不确定(c == '?'),球可能传递到 (j + r) % n 或 (j - r + n) % n。
代码如下
点击查看代码
#include <bits/stdc++.h>
#define i64 long long
using namespace std;
void solve(){int n, m, x;cin >> n >> m >> x;vector <vector <i64>> f (m + 1, vector <i64> (n + 1, 0)); f[0][x - 1] = 1;for(int i = 1; i <= m; i++){i64 b;char c;cin >> b >> c;for(int j = 0; j < n; j++){if(f[i - 1][j]){if(c == '0') f[i][(j + b) % n] = 1;else if(c == '1') f[i][(j - b + n) % n] = 1;else {f[i][(j - b + n) % n] = 1;f[i][(j + b) % n] = 1;}}}}vector <int> result;for(int i = 0; i < n; i++){if(f[m][i]) result.push_back(i);}cout << result.size() << endl;for(int i = 0; i < result.size(); i++) cout << result[i] + 1 << ' ';cout << endl;
}
int main()
{int t;cin >> t;while(t--){solve();}
}