CCPC Finals 2021 (A F G J L)

编程入门 行业动态 更新时间:2024-10-05 23:18:18

<a href=https://www.elefans.com/category/jswz/34/1764279.html style=CCPC Finals 2021 (A F G J L)"/>

CCPC Finals 2021 (A F G J L)

CCPC Finals 2021 (A F G J L)

Problem - A - Codeforces

A. Mash(模拟)

思路:由于需要执行的指令条数 k 是有限的 , 考虑直接用队列模拟即可。

时间复杂度 O ( n + k ) 时间复杂度O(n + k) 时间复杂度O(n+k)

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define int long long
const int INF = 9e18;
const int N = 2e6 + 10;
const int mod = 1e9 + 7;
typedef pair<int,int>PII;struct node{string op;char c;int cnt;
}a[N];int n , cnt;
string ans;signed main(){cin >> n >> cnt;queue<node>q;for(int i = 1 ; i <= n ; i ++) {string s;char c;int x = 0;cin >> s;if(s[0] == 'e') {a[i].op = "echo";cin >> c;a[i].c = c;} else {a[i].op = "cp";cin >> x;a[i]t = x;}if(cnt) q.push(a[i]);cnt -= 1;}while(cnt) {if(q.size() == 0) break;node now = q.front();q.pop();if(now.op == "echo") {ans += now.c;} else {for(int i = 1 ; i <= nowt && cnt ; i ++) {q.push(a[i]);cnt -= 1;}}}while(q.size()) {node now = q.front();q.pop();if(now.op == "echo") {ans += now.c;}}cout << ans << "\n";return 0;
}
//freopen("文件名.in","r",stdin);
//freopen("文件名.out","w",stdout);

F. Modulo(枚举)

思路:考虑取模运算 , 对比自己大的数取模是没有意义的 , 对数列排序后 , 考虑每次选择比自己小的数作为模数 , 搜索即可 。这样操作当前的数存在单调性 , 所以不会选到两个相同的数。

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define int long long
const int INF = 9e18;
const int N = 2e6 + 10;
const int mod = 1e9 + 7;
typedef pair<int,int>PII;int n , a[N] , x , res = -INF;void dfs(int x){int pos = upper_bound(a + 1 , a + 1 + n , x) - a - 1;if(pos == 0) {res = max(res , x);return ;} else {for(int i = 1 ; i <= pos ; i ++) {dfs(x % a[i]);}}
}signed main(){cin >> n;for(int i = 1 ; i <= n ; i ++) {cin >> a[i];}cin >> x;sort(a + 1 , a + 1 + n);dfs(x);cout << res << "\n";	return 0;
}
//freopen("文件名.in","r",stdin);
//freopen("文件名.out","w",stdout);

G. Integer Game(SG打表 ,博弈论)

思路:考虑各个游戏之间都是独立的 , 计算每一个游戏的 SG 值 , 根据 SG 定理去求先手胜负情况。 对于每一个独立游戏的SG值考虑打表。

打表函数:

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define int long long
const int INF = 9e9;
const int N = 2e6 + 10;
const int mod = 1e9 + 7;
typedef pair<int,int>PII;int l , r , p;int dp[100][100][100];int get(int l , int r , int p) {//异或值有含义注意这里什么都不写!!!!if(dp[l][r][p] != -1) return dp[l][r][p];int pos = (r - 1) / p + 1;set<int>st;for(int i = max(pos , l) ; i <= r ; i ++) {st.insert(get(l , i - 1 , p));}for(int i = 0 ; ; i ++) if(!st.count(i)) return dp[l][r][p] = i;
}signed main(){memset(dp , -1 , sizeof(dp));for(int p = 1 ; p <= 20 ; p ++){cout << "P = " << p << "\n";for(int i = 1 ; i <= 5 ; i ++) {cout << "L = " << i << "\n";cout << "pos:";
//			for(int j = i , k = 1 ; j <= 30 ; j ++ , k += 1) {
//				cout << setw(3) << k;
//			}//未偏移for(int j = i ; j <= 30 ; j ++ ) {cout << setw(3) << j;}//偏移cout << "\n";cout << "val:";for(int j = i ; j <= 30 ; j ++) {cout << setw(3) << get(i , j , p);}cout << "\n\n";}}return 0;
}
//freopen("文件名.in","r",stdin);
//freopen("文件名.out","w",stdout);

规律就是 , 固定 P , L 之后 , 每个相同的 SG 值的位置(R)之间有一个

R i = R i − 1 ∗ p + ( p + 1 ) R_i=R_{i-1}*p+(p+1) Ri​=Ri−1​∗p+(p+1)

的关系 , 对于给出的一个右端点 , 考虑跳到SG值相同的最小位置处 , 显然每一个SG值第一次出现的位置和值之前有一个很明显的关系 , 根据关系把位置坐标对应到SG值即可。

时间复杂度 O ( n l o g r ) 时间复杂度O(nlogr) 时间复杂度O(nlogr)

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define int long long
const int INF = 9e18;
const int N = 2e6 + 10;
const int mod = 1e9 + 7;
typedef pair<int,int>PII;/*
*p + (p + 1)
5 5 1
*/int get(int l , int r , int p) {while((r - (p + 1)) % p == 0 && (r - (p + 1)) / p >= l) r = (r - (p + 1)) / p;r -= (l - 1);int rd = l * (p - 1) + 2;if(r <= rd) {if(r == rd) {return 0;} else {return r;}} else {int cnt = (r - rd - 1) / p + 1;return r - cnt;}
}int t , l , r , n , p;signed main(){IOScin >> t;while(t --) {cin >> n >> p;int ok = 0;for(int i = 1 ; i <= n ; i ++) {cin >> l >> r;ok ^= get(l , r , p);}if(ok == 0) {cout << "Second\n";} else {cout << "First\n";}}return 0;
}
//freopen("文件名.in","r",stdin);
//freopen("文件名.out","w",stdout);

J. jwfw.harie.edu(折半搜索)

思路:考虑最暴力的做法 , 即枚举所有可能的情况 , 然后和所有的条件比较

复杂度 O ( 4 10 ∗ n ∗ 10 ) 复杂度O(4^{10}*n*10) 复杂度O(410∗n∗10)

这个复杂度显然不能接受 , 考虑优化 , 折半搜索。即枚举出前五个字母 , 记录每一个状态对应的后五个应该有的状态 ,然后再枚举后五个的状态 , 计数即可。

由于状态是一个序列 , 需要哈希一下 , 双哈希 , 单哈希会被卡掉

复杂度 O ( 4 5 ∗ ( 5 n + n + l o g ( 4 5 ) ) ) 复杂度O(4^{5}*(5n+n+log(4^5))) 复杂度O(45∗(5n+n+log(45)))

log 是 map 的复杂度 , n 是哈希的复杂度 , 5n 是计算状态的复杂度。

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define int long long
const int INF = 9e18;
const int N = 2e4 + 10;
const int mod = 1e9 + 7;
typedef pair<int,int>PII;string s[1500];
int cnt , t , n;
int need[N];//--------------------------------------------------------------------------------
const int mod1 = 1e9 + 7;
const int mod2 = 1e9 + 9;
const int Base1 = 131;
const int Base2 = 13331;
int base1[N] , h1[N] , base2[N] , h2[N];inline void init_hash(int n){base1[0] = base2[0] = 1;for(int i = 1 ; i <= n ; i ++) base1[i] = base1[i - 1] * Base1 % mod1;for(int i = 1 ; i <= n ; i ++) base2[i] = base2[i - 1] * Base2 % mod2; 
}inline PII get(int n){h1[0] = h2[0] = 0;for(int i = 1 ; i <= n ; i ++) h1[i] = (h1[i - 1] * Base1 % mod1 + need[i - 1]) % mod1;for(int i = 1 ; i <= n ; i ++) h2[i] = (h2[i - 1] * Base2 % mod2 + need[i - 1]) % mod2;int x = ((h1[n] - h1[0] * base1[n]) % mod1 + mod1) % mod1;int y = ((h2[n] - h2[0] * base2[n]) % mod2 + mod2) % mod2;return {x , y};
}
//--------------------------------------------------------------------------------void dfs(int x , string s_now){if(x == 5) {s[++cnt] = s_now;return ;}for(char i = 'A' ; i <= 'D' ; i ++) {dfs(x + 1 , s_now + i);}
}signed main(){IOSdfs(0 , "");init_hash(N - 10);cin >> t;while(t --) {cin >> n;int res = 0;map<pair<int , int> , int> mp;vector<pair<string , int>>ve;for(int i = 1 ; i <= n ; i ++) {string s;int x;cin >> s >> x;ve.push_back({s , x / 10});}//第一半搜索for(int i = 1 ; i <= cnt ; i ++) {string now = s[i];bool ok = 1;for(int j = 0 ; j < n ; j ++) {string s = ve[j].first;int num = ve[j].second;int cnt = 0;for(int k = 0 ; k < 5 ; k ++) {if(s[k] == now[k]) cnt += 1;}if(cnt > num) {ok = 0;break;} else {need[j] = num - cnt;}}if(!ok) continue;PII val = get(n); mp[val] += 1;}	//第二半搜索for(int i = 1 ; i <= cnt ; i ++) {string now = s[i];for(int j = 0 ; j < n ; j ++) {string s = ve[j].first;int num = ve[j].second;int cnt = 0;for(int k = 5 ; k < 10 ; k ++) {if(s[k] == now[k - 5]) cnt += 1;}need[j] = cnt;}PII val = get(n); if(mp.find(val) != mp.end()) res += mp[val];}	cout << res << "\n";}return 0;
}
//freopen("文件名.in","r",stdin);
//freopen("文件名.out","w",stdout);

L. Paid Leave (贪心)

思路:对于每一个需要填充的区间 , 考虑贪心填充 , 最小化贡献 。 需要注意的是 , 每一个区间的 y 不变 , 但是 x 是会被前一个区间影响的 , 动态更新即可。

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define int long long
const int INF = 9e18;
const int N = 2e6 + 10;
const int mod = 1e9 + 7;
typedef pair<int,int>PII;int n , m , x , y;
int pos[N] , dis[N];signed main(){cin >> n >> m >> x >> y;for(int i = 1 ; i <= m ; i ++) {cin >> pos[i];dis[i] = pos[i] - pos[i - 1] - 1;}m += 1;dis[m] = (n + 1) - pos[m - 1] - 1;int need = y + 2;int res = 0 , l = 0 , pre = 0;for(int i = 1 ; i <= m ; i ++) {l = min(x , y - pre);int cnt = dis[i] / need;int oth = dis[i] % need;res += cnt * 2;if(oth > l) {res += 1;pre = oth - (l + 1);} else {pre = oth;}}cout << res << "\n";return 0;
}
//freopen("文件名.in","r",stdin);
//freopen("文件名.out","w",stdout);

更多推荐

CCPC Finals 2021 (A F G J L)

本文发布于:2024-03-09 03:37:12,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1723653.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:CCPC   Finals

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!