2022 四川某化工大学新生赛
复建第一题,上去找找比赛打打,看见某校新生赛正在running就进来转转,反正回复下手感就得从初级题开始,几个月不练的帐也得给补上
A题,水题,切了
#include <bits/stdc++.h> using namespace std; constexpr int limit = (1000000 + 5);//防止溢出 #define INF 0x3f3f3f3f #define inf 0x3f3f3f3f3f #define lowbit(i) i&(-i)//一步两步 #define EPS 1e-9 #define FASTIO ios::sync_with_stdio(false);cin.tie(0),cout.tie(0); #define ff(a) printf("%d\n",a ); #define pi(a, b) pair<a,b> #define rep(i, a, b) for(ll i = a; i <= b ; ++i) #define per(i, a, b) for(ll i = b ; i >= a ; --i) #define MOD 998244353 #define traverse(u) for(int i = head[u]; ~i ; i = edge[i].next) #define FOPEN freopen("C:\\Users\\tiany\\CLionProjects\\akioi\\data.txt", "rt", stdin) #define FOUT freopen("C:\\Users\\tiany\\CLionProjects\\akioi\\dabiao.txt", "wt", stdout) typedef long long ll; typedef unsigned long long ull; char buf[1 << 23], *p1 = buf, *p2 = buf, obuf[1 << 23], *O = obuf; inline ll read() { #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) ll sign = 1, x = 0; char s = getchar(); while (s > '9' || s < '0') { if (s == '-')sign = -1; s = getchar(); } while (s >= '0' && s <= '9') { x = (x << 3) + (x << 1) + s - '0'; s = getchar(); } return x * sign; #undef getchar }//快读 void print(ll x) { if (x / 10) print(x / 10); *O++ = x % 10 + '0'; } void write(ll x, char c = 't') { if (x < 0)putchar('-'), x = -x; print(x); if (!isalpha(c))*O++ = c; fwrite(obuf, O - obuf, 1, stdout); O = obuf; } int n, m, k; int a[limit]; int dp[limit]; void solve() { string str; cin>>str; str.reserve(4); reverse(str.begin(), str.end()); while(str.length() < 4){ str.push_back('0'); } reverse(str.begin(), str.end()); cout<<str<<endl; } int32_t main() { #ifdef LOCAL FOPEN; // FOUT; #endif FASTIO // int kase; // cin >> kase; // while (kase--) solve(); cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << "s\n"; return 0; }
B题,也就是简单模拟,没啥难度
#include <bits/stdc++.h> using namespace std; constexpr int limit = (1000000 + 5);//防止溢出 #define INF 0x3f3f3f3f #define inf 0x3f3f3f3f3f #define lowbit(i) i&(-i)//一步两步 #define EPS 1e-9 #define FASTIO ios::sync_with_stdio(false);cin.tie(0),cout.tie(0); #define ff(a) printf("%d\n",a ); #define pi(a, b) pair<a,b> #define rep(i, a, b) for(ll i = a; i <= b ; ++i) #define per(i, a, b) for(ll i = b ; i >= a ; --i) #define MOD 998244353 #define traverse(u) for(int i = head[u]; ~i ; i = edge[i].next) #define FOPEN freopen("C:\\Users\\tiany\\CLionProjects\\akioi\\data.txt", "rt", stdin) #define FOUT freopen("C:\\Users\\tiany\\CLionProjects\\akioi\\dabiao.txt", "wt", stdout) typedef long long ll; typedef unsigned long long ull; char buf[1 << 23], *p1 = buf, *p2 = buf, obuf[1 << 23], *O = obuf; inline ll read() { #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) ll sign = 1, x = 0; char s = getchar(); while (s > '9' || s < '0') { if (s == '-')sign = -1; s = getchar(); } while (s >= '0' && s <= '9') { x = (x << 3) + (x << 1) + s - '0'; s = getchar(); } return x * sign; #undef getchar }//快读 void print(ll x) { if (x / 10) print(x / 10); *O++ = x % 10 + '0'; } void write(ll x, char c = 't') { if (x < 0)putchar('-'), x = -x; print(x); if (!isalpha(c))*O++ = c; fwrite(obuf, O - obuf, 1, stdout); O = obuf; } #define int ull int n, m, k; int a[limit]; int dp[limit]; void solve() { ll ans = 0; cin>>n; per(i, 0, 63){ if((1ull<<i) <= n) { cout<<i<<endl; break; } } } int32_t main() { #ifdef LOCAL FOPEN; // FOUT; #endif FASTIO // int kase; // cin >> kase; // while (kase--) solve(); cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << "s\n"; return 0; }
C题,给出一个n和k和一个01串,只能在1的地方落脚,一次最多走k格,问最小跳跃次数,这个就是很简单的dp,没什么难度
#include <bits/stdc++.h> using namespace std; constexpr int limit = (1000000 + 5);//防止溢出 #define INF 0x3f3f3f3f #define inf 0x3f3f3f3f3f #define lowbit(i) i&(-i)//一步两步 #define EPS 1e-9 #define FASTIO ios::sync_with_stdio(false);cin.tie(0),cout.tie(0); #define ff(a) printf("%d\n",a ); #define pi(a, b) pair<a,b> #define rep(i, a, b) for(ll i = a; i <= b ; ++i) #define per(i, a, b) for(ll i = b ; i >= a ; --i) #define MOD 998244353 #define traverse(u) for(int i = head[u]; ~i ; i = edge[i].next) #define FOPEN freopen("C:\\Users\\tiany\\CLionProjects\\akioi\\data.txt", "rt", stdin) #define FOUT freopen("C:\\Users\\tiany\\CLionProjects\\akioi\\dabiao.txt", "wt", stdout) typedef long long ll; typedef unsigned long long ull; char buf[1 << 23], *p1 = buf, *p2 = buf, obuf[1 << 23], *O = obuf; inline ll read() { #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) ll sign = 1, x = 0; char s = getchar(); while (s > '9' || s < '0') { if (s == '-')sign = -1; s = getchar(); } while (s >= '0' && s <= '9') { x = (x << 3) + (x << 1) + s - '0'; s = getchar(); } return x * sign; #undef getchar }//快读 void print(ll x) { if (x / 10) print(x / 10); *O++ = x % 10 + '0'; } void write(ll x, char c = 't') { if (x < 0)putchar('-'), x = -x; print(x); if (!isalpha(c))*O++ = c; fwrite(obuf, O - obuf, 1, stdout); O = obuf; } int n, m, k; int a[limit]; int dp[limit]; void solve() { cin>>n>>k; string str; cin>>str; str = ' ' + str; fill(dp, dp + 1 + n, INF); dp[0] = dp[1] = 0; rep(i,1,n){ if(str[i] == '0')continue; per(j, i - k, i - 1){ if(j <= 0)break; if(str[j] == '0')continue; dp[i] = min(dp[i], dp[j] + 1); } } cout<<(dp[n] < INF ? dp[n] : -1)<<endl; } int32_t main() { #ifdef LOCAL FOPEN; // FOUT; #endif FASTIO // int kase; // cin >> kase; // while (kase--) solve(); cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << "s\n"; return 0; }
D题,给出一个数字n,要求给出n个互不相同的长度为2n的合法括号串,这个一开始想爆搜,后来模拟之后发现我们只需要维护当前有多少左括号即可,一个右括号是-1,一个左括号对于cnt的影响是+1,很显然如果要合法,那么cnt为0的时候我们只能放左括号,如果cnt大于0我们可以左括号和右括号都放,最后再判断一下长度就好了
#include <bits/stdc++.h> using namespace std; constexpr int limit = (100000 + 5);//防止溢出 #define INF 0x3f3f3f3f #define inf 0x3f3f3f3f3f #define lowbit(i) i&(-i)//一步两步 #define EPS 1e-9 #define FASTIO ios::sync_with_stdio(false);cin.tie(0),cout.tie(0); #define ff(a) printf("%d\n",a ); #define pi(a, b) pair<a,b> #define rep(i, a, b) for(ll i = a; i <= b ; ++i) #define per(i, a, b) for(ll i = b ; i >= a ; --i) #define MOD 998244353 #define traverse(u) for(int i = head[u]; ~i ; i = edge[i].next) #define FOPEN freopen("C:\\Users\\tiany\\CLionProjects\\akioi\\data.txt", "rt", stdin) #define FOUT freopen("C:\\Users\\tiany\\CLionProjects\\akioi\\dabiao.txt", "wt", stdout) typedef long long ll; typedef unsigned long long ull; char buf[1 << 23], *p1 = buf, *p2 = buf, obuf[1 << 23], *O = obuf; inline ll read() { #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) ll sign = 1, x = 0; char s = getchar(); while (s > '9' || s < '0') { if (s == '-')sign = -1; s = getchar(); } while (s >= '0' && s <= '9') { x = (x << 3) + (x << 1) + s - '0'; s = getchar(); } return x * sign; #undef getchar }//快读 void print(ll x) { if (x / 10) print(x / 10); *O++ = x % 10 + '0'; } void write(ll x, char c = 't') { if (x < 0)putchar('-'), x = -x; print(x); if (!isalpha(c))*O++ = c; fwrite(obuf, O - obuf, 1, stdout); O = obuf; } int n, m, k; int a[limit]; vector<string>ans; int tot; void dfs(string str, int cnt){ if(ans.size() >= n)return; if(str.length() == 2 * n && cnt == 0){ ans.push_back(str); return; } if(str.length() >= 2 * n)return; if(cnt > 0){ dfs(str + ')', cnt - 1 ); dfs(str + '(', cnt + 1); }else if(cnt == 0){ dfs(str + '(', cnt + 1); }else{ return; } } void solve() { cin>>n; ans.clear(); dfs("", 0); for(const auto & it : ans){ cout<<it<<endl; } } int32_t main() { #ifdef LOCAL FOPEN; // FOUT; #endif FASTIO int kase; cin >> kase; while (kase--) solve(); cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << "s\n"; return 0; }
E题,给一个函数f(x) = 大于x的最小质数,问g(x) = (f(x) + f(f(x))) / 2是否是质数
这个我以为是什么难题,但是想了下发现数字范围都在int128范围内,可以做。
我们预处理出来1e5范围内素数,然后就能用二分法 + 乘法快速求出f(x), 最后再用罗宾米勒算法判断是不是质数,但是需要注意,这题没法用phi,用phi铁超时,烦人
#include <bits/stdc++.h> using namespace std; constexpr int limit = (100000 + 5);//防止溢出 #define INF 0x3f3f3f3f #define inf 0x3f3f3f3f3f #define lowbit(i) i&(-i)//一步两步 #define EPS 1e-9 #define FASTIO ios::sync_with_stdio(false);cin.tie(0),cout.tie(0); #define ff(a) printf("%d\n",a ); #define pi(a, b) pair<a,b> #define rep(i, a, b) for(ll i = a; i <= b ; ++i) #define per(i, a, b) for(ll i = b ; i >= a ; --i) #define MOD 998244353 #define traverse(u) for(int i = head[u]; ~i ; i = edge[i].next) #define FOPEN freopen("C:\\Users\\tiany\\CLionProjects\\akioi\\data.txt", "rt", stdin) #define FOUT freopen("C:\\Users\\tiany\\CLionProjects\\akioi\\dabiao.txt", "wt", stdout) typedef __int128 ll; typedef unsigned long long ull; char buf[1 << 23], *p1 = buf, *p2 = buf, obuf[1 << 23], *O = obuf; inline ll read() { #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) ll sign = 1, x = 0; char s = getchar(); while (s > '9' || s < '0') { if (s == '-')sign = -1; s = getchar(); } while (s >= '0' && s <= '9') { x = (x << 3) + (x << 1) + s - '0'; s = getchar(); } return x * sign; #undef getchar }//快读 void print(ll x) { if (x / 10) print(x / 10); *O++ = x % 10 + '0'; } void write(ll x, char c = 't') { if (x < 0)putchar('-'), x = -x; print(x); if (!isalpha(c))*O++ = c; fwrite(obuf, O - obuf, 1, stdout); O = obuf; } int num[limit]; int prime[limit],tot; void make_prime(int N = 1e5){ memset(num, 1, sizeof(num)); num[1] = num[0] = 0; tot = 0; rep(i, 2,N){ if(num[i])prime[++tot] = i; for(ll j = 1; j <= tot && i * prime[j] <= N; ++j){ num[i * prime[j]] = 0; if(i % prime[j] == 0)break;//断开 } } }//欧拉筛 int n, m, k; int a[limit]; ll f(ll x){ auto it = upper_bound(prime + 1, prime + 1 + tot, x); if(it != prime + 1 + tot){ return *it; } ll sum = 1; rep(i,1, tot){ sum *= prime[i]; if(sum > x)break; } return sum; } ll qpow(ll a, ll n, ll p) // 快速幂 { ll ans = 1; while (n) { if (n & 1) ans = (__int128)ans * a % p; // 注意!中间结果可能溢出,需要使用__int128过渡 a = (__int128)a * a % p; n >>= 1; } return ans; } bool valid(ll x) { if (x < 3) // 特判1,2 return x == 2; if (x % 2 == 0) // 特判偶数 return false; ll A[] = {2, 325, 9375, 28178, 450775, 9780504, 1795265022}, d = x - 1, r = 0; while (d % 2 == 0) // 算出d, r d /= 2, ++r; // 或:r = __builtin_ctz(d), d >>= r; for (auto a : A) { ll v = qpow(a, d, x); // a^d // 如果a^d≡0,说明是a是x的倍数;如果a^d≡1或-1,说明这串数接下来一定都是1,不用继续计算 if (v <= 1 || v == x - 1) continue; for (int i = 0; i < r; ++i) { v = (__int128)v * v % x; // 同样使用__int128过渡 if (v == x - 1 && i != r - 1) // 得到-1,说明接下来都是1,可以退出了 { v = 1; break; } // 在中途而非开头得到1,却没有经过-1,说明存在其他数字y≠-1满足y^2≡1,则x一定不是奇素数 if (v == 1) return false; } if (v != 1) // 查看是不是以1结尾 return false; } return true; } void solve() { ll x; x = read(); auto ans = (f(x) + f(f(x))) / 2; if(valid(ans)){ puts("YES"); }else{ puts("NO"); } } int32_t main() { #ifdef LOCAL FOPEN; // FOUT; #endif // FASTIO make_prime(); int kase; kase = read(); while (kase--) solve(); // cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << "s\n"; return 0; }
F题,给出一个01串,可以分成任意段,问mex的总和最小是多少
这个题其实不难,首先我们发现可以合并连续相同的段,然后判断最后是不是全是1或者全是0,如果不是的话,看看如果把1都单拿出来,0的贡献和2哪个小就行了(因为01串什么都不做,mex最大就是2)
#include <bits/stdc++.h> using namespace std; constexpr int limit = (100000 + 5);//防止溢出 #define INF 0x3f3f3f3f #define inf 0x3f3f3f3f3f #define lowbit(i) i&(-i)//一步两步 #define EPS 1e-9 #define FASTIO ios::sync_with_stdio(false);cin.tie(0),cout.tie(0); #define ff(a) printf("%d\n",a ); #define pi(a, b) pair<a,b> #define rep(i, a, b) for(ll i = a; i <= b ; ++i) #define per(i, a, b) for(ll i = b ; i >= a ; --i) #define MOD 998244353 #define traverse(u) for(int i = head[u]; ~i ; i = edge[i].next) #define FOPEN freopen("C:\\Users\\tiany\\CLionProjects\\akioi\\data.txt", "rt", stdin) #define FOUT freopen("C:\\Users\\tiany\\CLionProjects\\akioi\\dabiao.txt", "wt", stdout) typedef long long ll; typedef unsigned long long ull; char buf[1 << 23], *p1 = buf, *p2 = buf, obuf[1 << 23], *O = obuf; inline ll read() { #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) ll sign = 1, x = 0; char s = getchar(); while (s > '9' || s < '0') { if (s == '-')sign = -1; s = getchar(); } while (s >= '0' && s <= '9') { x = (x << 3) + (x << 1) + s - '0'; s = getchar(); } return x * sign; #undef getchar }//快读 void print(ll x) { if (x / 10) print(x / 10); *O++ = x % 10 + '0'; } void write(ll x, char c = 't') { if (x < 0)putchar('-'), x = -x; print(x); if (!isalpha(c))*O++ = c; fwrite(obuf, O - obuf, 1, stdout); O = obuf; } int n, m, k; int a[limit]; void solve() { string str; cin>>str; string ans; for(auto it: str){ if(ans.empty()){ ans.push_back(it); continue; } if(ans.back() == it)continue; ans.push_back(it); } if(ans.length() == 1){ cout<<(ans.back() == '0' ? 1 : 0)<<endl; return; } cout<<min(2, (int)count(ans.begin(), ans.end(), '0'))<<endl; } int32_t main() { #ifdef LOCAL FOPEN; // FOUT; #endif FASTIO int kase; cin>>kase; while (kase--) solve(); // cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << "s\n"; return 0; }
H题,给出a和b,求最大最小的c,使得a mod c == b mod c,这题我似乎在哪见过,但想不起来,就是特判就好了,当两者相差为1的时候,不存在答案,其他的话就用差值或者看最小的是否为2,当a和b相同的时候,我们看看a和b能不能作为c,即c >= 1,如果可以的话就是2 a或者b, 如果不行的话就是-1 -1, 其他的话首先找到差值,另外从差值我们自然想到差值的因数应该也可以当作c,证明很简单,不列出,然后我们因式分解以下取最小的因子当作最小的c,差值当作大c就好了,如果是质数,那么就用差值当作上下界好了。其实我想到这个的原因是,1919810,这个样例味道太冲了,肯定在提示质数,所以就想到后面的了
坑点就是hdu系列的oj不能用cerr,我还以为哪写错了debug了半天。。。。
#include <bits/stdc++.h> using namespace std; constexpr int limit = (100000 + 5);//防止溢出 #define INF 0x3f3f3f3f #define inf 0x3f3f3f3f3f #define lowbit(i) i&(-i)//一步两步 #define EPS 1e-9 #define FASTIO ios::sync_with_stdio(false);cin.tie(0),cout.tie(0); #define ff(a) printf("%d\n",a ); #define pi(a, b) pair<a,b> #define rep(i, a, b) for(ll i = a; i <= b ; ++i) #define per(i, a, b) for(ll i = b ; i >= a ; --i) #define MOD 998244353 #define traverse(u) for(int i = head[u]; ~i ; i = edge[i].next) #define FOPEN freopen("C:\\Users\\tiany\\CLionProjects\\akioi\\data.txt", "rt", stdin) #define FOUT freopen("C:\\Users\\tiany\\CLionProjects\\akioi\\dabiao.txt", "wt", stdout) typedef long long ll; typedef unsigned long long ull; char buf[1 << 23], *p1 = buf, *p2 = buf, obuf[1 << 23], *O = obuf; inline ll read() { #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) ll sign = 1, x = 0; char s = getchar(); while (s > '9' || s < '0') { if (s == '-')sign = -1; s = getchar(); } while (s >= '0' && s <= '9') { x = (x << 3) + (x << 1) + s - '0'; s = getchar(); } return x * sign; #undef getchar }//快读 void print(ll x) { if (x / 10) print(x / 10); *O++ = x % 10 + '0'; } void write(ll x, char c = 't') { if (x < 0)putchar('-'), x = -x; print(x); if (!isalpha(c))*O++ = c; fwrite(obuf, O - obuf, 1, stdout); O = obuf; } ll n, m, k; int a[limit]; void solve() { cin>>n>>m; ll ans = llabs(n - m); if(n == m){ if(n <= 1){ cout<<-1<<" "<<-1<<endl; }else{ cout<<2<<" "<<n<<endl; } return; } if(ans <= 1){ cout<<-1<<" "<<-1<<endl; return; } for(int i = 2; i * i <= ans; ++i){ if(ans % i == 0){ cout<<i<<" "<<ans<<endl; return; } } cout<<ans<<" "<<ans<<endl; } int32_t main() { #ifdef LOCAL FOPEN; // FOUT; #endif FASTIO int kase; cin >> kase; while (kase--) solve(); // cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << "s\n"; return 0; }
写完就手工吧,下午搞一搞项目,今天的算法就到这里了