The 2021 Sichuan Provincial Collegiate Programming Contest
思路:
可以打表,但不如枚举快,枚举就从1到6两重循环,由于1,3 3,1算一种,所以第二重直接从i开始就可以
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <set> #include <vector> #include <map> #include <unordered_set> #include <unordered_map> #define x first #define y second #define IOS ios::sync_with_stdio(false);cin.tie(0); using namespace std; typedef long long LL; typedef pair<int, int> PII; const int N = 100010, MOD = 1000000007, INF = 0x3f3f3f3f; int main() { IOS; int T; cin >> T; while(T -- ) { int k; cin >> k; int res = 0; for (int i = 1; i <= 6; i ++ ) for (int j = i; j <= 6; j ++ ) if(i + j == k) res++; cout << res << endl; } return 0; }
思路:
由于m太大所以必然不能遍历m次操作,我们可以把2n次操作算作一轮,然后可以把这m次操作分成若干轮,找找有多少次这样的2n轮,最后凑不成一轮的多出来的几次操作单独遍历处理就可以了
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <set> #include <vector> #include <map> #include <unordered_set> #include <unordered_map> #define x first #define y second #define IOS ios::sync_with_stdio(false);cin.tie(0); using namespace std; typedef long long LL; typedef pair<int, int> PII; const int N = 100010, MOD = 1000000007, INF = 0x3f3f3f3f; PII pot[N]; bool st[N]; int main() { IOS; int T; cin >> T; while(T -- ) { int n, k, m; cin >> n >> k >> m; memset(st, 0, sizeof st); for (int i = 0; i < n; i ++ ) { cin >> pot[i].first; pot[i].second = 0; } for (int i = 0; i < 2 * n; i ++ ) { int idx = i % n; if(st[pot[idx].first]) { st[pot[idx].first] = 0; pot[idx].second++; } else st[pot[idx].first] = 1; } int tmp = m / (2 * n);//m中有多少个2n for (int i = 0; i < n; i ++ ) pot[i].second *= tmp; int mod = m % (2 * n);//多出来的几个单独处理 for (int i = 0; i < mod; i ++ ) { int idx = i % n; if (st[pot[idx].first]) { st[pot[idx].first] = 0; pot[idx].second++; } else st[pot[idx].first] = 1; } for (int i = 0; i < n - 1; i ++ ) cout << pot[i].second << ' '; cout << pot[n - 1].second << endl; } return 0; }
思路:
先手的所有出牌情况都不会影响结果,只能是后手才会影响,而后手会优先考虑赢的情况,然后是平局,最后才是输的情况,所以依次判断先手石头剪刀布的后手情况即可,记得开long long
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <set> #include <vector> #include <map> #include <unordered_set> #include <unordered_map> #define int LL #define x first #define y second #define IOS ios::sync_with_stdio(false);cin.tie(0); using namespace std; typedef long long LL; typedef pair<int, int> PII; const int N = 100010, MOD = 1000000007, INF = 0x3f3f3f3f; PII pot[N]; bool st[N]; signed main() { IOS; int T; cin >> T; while(T -- ) { int br, bp, bs, dr, dp, ds; cin >> br >> bp >> bs >> dr >> dp >> ds; int res = 0; if(br) { if(dp && br)//赢 { int tmp = min(dp, br); res += tmp; dp -= tmp; br -= tmp; } if(dr && br)//平 { int tmp = min(dr, br); dr -= tmp; br -= tmp; } if(ds && br)//输 { int tmp = min(ds, br); res -= tmp; ds -= tmp; br -= tmp; } } if (bp) { if (ds && bp) //赢 { int tmp = min(ds, bp); res += tmp; ds -= tmp; bp -= tmp; } if (dp && bp) //平 { int tmp = min(dp, bp); dp -= tmp; bp -= tmp; } if (dr && bp) //输 { int tmp = min(dr, bp); res -= tmp; ds -= tmp; br -= tmp; } } if (bs) { if (dr && bs) //赢 { int tmp = min(dr, bs); res += tmp; dr -= tmp; bs -= tmp; } if (ds && bs) //平 { int tmp = min(ds, bs); ds -= tmp; bs -= tmp; } if (dp && bs) //输 { int tmp = min(dp, bs); res -= tmp; dp -= tmp; bs -= tmp; } } cout << res << endl; } return 0; }
E - Don't Really Like How The Story Ends
思路:
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <set> #include <vector> #include <map> #include <unordered_set> #include <unordered_map> #define int LL #define x first #define y second #define IOS ios::sync_with_stdio(false);cin.tie(0); using namespace std; typedef long long LL; typedef pair<int, int> PII; const int N = 100010, MOD = 1000000007, INF = 0x3f3f3f3f; int n, m; int nxt, res; vector<int> g[N]; //u表示当前点序号,nxt表示下一个要到的点的序号 void dfs(int u) { if(u == n + 1) return; for (auto x : g[u]) { if(x < nxt) continue; while(x >= nxt) { if(x == nxt) nxt++, dfs(nxt - 1);//nxt指向下一个要到的点,nxt-1表示上次的nxt变成了现在的点,并dfs这个点 else if(x > nxt) res++, nxt++, dfs(nxt - 1); } } } signed main() { IOS; int T; cin >> T; while(T -- ) { for (int i = 1; i <= n; i ++ ) g[i].clear(); cin >> n >> m; while(m -- ) { int a, b; cin >> a >> b; g[a].push_back(b), g[b].push_back(a); } g[1].push_back(n + 1);//为了方便让1和n+1相连 for (int i = 1; i <= n; i ++ ) sort(g[i].begin(), g[i].end()); nxt = 2, res = 0; dfs(1); cout << res << endl; } return 0; }
L - Spicy Restaurant
思路:
这题有点东西,这题是用w值来bfs,有点类似反推,就好比本来要从1号结点走到3号结点,那么现在的过程就转化成了从3号结点开始宽搜反着搜到1号结点,那么我们最多bfs100次即可得出所有的情况
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <set> #include <vector> #include <map> #include <unordered_set> #include <unordered_map> #define x first #define y second #define IOS ios::sync_with_stdio(false);cin.tie(0); using namespace std; typedef long long LL; typedef pair<int, int> PII; const int N = 110, M = 100010, MOD = 1000000007, INF = 0x3f3f3f3f; int n, m, q; int e[2 * M], ne[2 * M], h[M], idx; int w[M]; int dist[M][N]; //dist[i][j]表示距离i最近的属性值恰好为j的点的距离 bool st[M]; void add(int a, int b) { e[idx] = b, ne[idx] = h[a], h[a] = idx++; } void bfs(int v) { memset(st, 0, sizeof st); queue<int> q; for (int i = 1; i <= n; i++) if (w[i] == v) { q.push(i); st[i] = true; dist[i][v] = 0; } while (!q.empty()) { auto t = q.front(); q.pop(); for (int i = h[t]; i != -1; i = ne[i]) { int j = e[i]; if (st[j]) continue; st[j] = true; dist[j][v] = dist[t][v] + 1; q.push(j); } } } signed main() { ios::sync_with_stdio(false); cin.tie(0); memset(h, -1, sizeof h); cin >> n >> m >> q; for (int i = 1; i <= n; i++) cin >> w[i]; while (m--) { int a, b; cin >> a >> b; add(a, b), add(b, a); } for (int i = 1; i <= n; i ++ ) for (int j = 1; j <= 100; j ++ ) dist[i][j] = INF; //注意dist的初始化不能在bfs里面,且memset会超时 for (int i = 1; i <= 100; i++) bfs(i); while (q--) { int cur, v; cin >> cur >> v; int res = INF; for (int i = 1; i <= v; i++) res = min(res, dist[cur][i]); if (res == INF) cout << -1 << endl; else cout << res << endl; } return 0; }

浙公网安备 33010602011771号