题目链接
编号
题意
个数,每个数介于 和 之间(可以为 或 )。对于每一个 选择一个数这个数在 到 之间,且选择的数不能重复。问一共有多少选择方案。
题解
从小到大排序后,假设当前你对前i个进行了选择,这 个选择的范围在 到 之间,对于第 个数它之中一定有 个数已经被选择过了,因为已经从小到大排过序了。所以对于每个 ,它对答案的贡献是使答案乘上 的结果。所以当 时是无解的。
代码
#include<bits/stdc++.h>
using namespace std;
#define int long longconst int mod = 1e9 + 7;void sl(){ int n; cin >> n; vector<int> a(n + 1); for(int i = 1 ;i <= n ;i++){ cin >> a[i]; } sort(a.begin() + 1,a.end()); int sum = 1; for(int i = 1 ;i <= n ;i++){ if(a[i] < i){ sum = 0; break; } sum = sum * (a[i] - i + 1) % mod; } cout << sum << '\n';}signed main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t = 1; // cin >> t; while(t--) sl(); return 0;}
小车问题
题意
两地的距离 ,初始两人在 地,人的步行速度 和车的速度 ,车一次只能载一人求两人同时到达 的所花费的最少时间。保证车速大于人的速度。
题解
假设先开车带一个人行驶了 距离,然后折返回去接第二个人,一路开到 点,且保证两人同时到达,由此可列出方程:
根据 可求出最后时间为:
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
void sl(){ double s,a,b; cin >> s >> a >> b; double x = (b + a) * s / (b + 3 * a); double t = x / b + (s - x) / a; cout << fixed << setprecision(6) << t << '\n';}signed main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t = 1; // cin >> t; while(t--) sl(); return 0;}
小凯的数字
题意
次询问,每次询问给一个 和 ,求出
后的结果。
题解
首先观察数据范围,发现询问次数在 次,每次的询问范围在 。因此可以判断该题应该是一道 的结论题。
首先观察 ,, 等等,发现结果都是 。因此可以大胆假设对于任意整数 ,有 (其中 为 到正无穷之间的整数)。
而对于 到 拼接起来形成的巨大数,可以看做 。根据之前的假设,将 的上标全部置为 在 意义下的结果是一样的,所以原式变为 。
因为我们最后需要对答案取模,为了防止取模后奇偶性发生改变,我们需要对 或者 单独除
代码
#include<bits/stdc++.h>
using namespace std;
#define int long longconst int mod = 9;
void sl(){ int l,r; cin >> l >> r; int sum; if((l + r) % 2 == 0){ sum = (((l + r) / 2 % mod) * ((r - l + 1) % mod)) % mod; }else{ sum = (((l + r) % mod) * ((r - l + 1) / 2 % mod)) % mod; } cout << sum << '\n';}signed main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t = 1; cin >> t; while(t--) sl(); return 0;}
平均数
题意
给一个长度为 的数列,我们需要找出该数列的一个连续子串,使得该子串平均数最大化,并且子串长度 。
题解
我们使用二分答案来解决这个问题。对于当前二分出的平均值,我们要确定它的合法性,可以通过以下步骤实现:
- 将所有数先减去平均值。
- 这时我们相当于是要找到一段区间,使得它的和大于
- 对减后的数组进行前缀和计算。
- 假设我们当前找到了
pre[i]
,只需要判断pre[1]
到pre[i - m]
之间的最小值是否小于pre[i]
,就可以判断出是否存在这样的区间。
代码
#include<bits/stdc++.h>
using namespace std;
#define int long longvoid sl(){ int n,m; cin >> n >> m; vector<int> a(n + 1); for(int i = 1 ;i <= n ;i ++){ cin >> a[i]; a[i] *= 10000; } auto check=[&](int x){ vector<int> b = a,pre(n + 1); int mn = 0; for(int i = 1 ;i <= n ;i++){ b[i] -= x; pre[i] = pre[i - 1] + b[i]; if(i >= m){ mn = min(mn,pre[i - m]); if(pre[i] > mn) return 1; } } return 0; }; int l = 0,r = 30000000; while(l <= r){ int mid = (l + r) >> 1; if(check(mid)) l = mid + 1; else r = mid - 1; } cout << l / 10 << '\n';}signed main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t = 1; // cin >> t; while(t--) sl(); return 0;}
Modified GCD
题意
有 组询问,每次询问 在 之间的最大公约数,如果不存在输出
题解
首先考虑 的最大公约数 与 其他公约数之间的关系,可以发现 的所有公约数均是最大公约数的因数。因此我们先处理出最大公约数的所有因数,然后对于每次询问的 进行二分查找即可。
代码
#include <bits/stdc++.h>
using namespace std;#define int long long
void sl( ){ int a,b,q; cin >> a >> b >> q; int gd = __gcd(a,b); set<int> p; for(int i = 1 ;i * i <= gd ;i ++){ if(gd % i == 0){ p.insert(i); p.insert(gd / i); } } while(q--){ int l,r; cin >> l >> r; if(gd < l){ cout << "-1\n"; continue; } if(gd <= r){ cout << gd << '\n'; continue; } auto it = p.upper_bound(r); it--; if(*it < l) cout << "-1\n"; else cout << *it << '\n'; }}
signed main( ){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t = 1; // cin>>t; while(t--) sl(); return 0;}
细胞分裂
题意
给你 与 ,并且给你 个数,假设第 个数为 ,找到最小的 使得,,如果不存在这样的 ,输出
题解
首先我们需要知道两个结论:
- ,将 和 质因数分解后, 为 的质因数集, 为 的质因数集,那么 为 的一个子集。
- 假设 是 的一个质因数, 可以分解出 个 ,而 可以分解出 个 。
之后我们在回来看题目,要保证 ,可以先对 进行质因数分解,并且对于每一个 同样进行质因数分解。如果 可以通过幂次操作使得取模结果为 0,那么 的每一个质因数也需要在 中出现,并且操作之后的每一个质因数的数量也要大于 的每一个质因数的数量乘上
代码
#include <bits/stdc++.h>
using namespace std;#define int long longconst int N = 3e4 + 10;
vector<int> prime;bool is[N];
void init(){ for(int i = 2 ;i < N ;i ++){ if(!is[i]){ prime.push_back(i); for(int j = i * i ;j < N ;j += i){ is[j] = 1; } } }}
void sl( ){ int m1,m2,n; cin >> n >> m1 >> m2; vector<int> a(n + 1); map<int,int> mp; int idx = 0; while(m1 > 1){ while(m1 % prime[idx] == 0){ mp[prime[idx]] ++; m1 /= prime[idx]; } idx++; } for(auto it : mp){ auto[u,v] = it; mp[u] *= m2; } int f = 0,num = -1; for(int i = 1 ;i <= n ;i ++){ cin >> a[i]; } for(int i = 1 ;i <= n ;i++){ int flag = 1,mn = 0; for(auto x : mp){ if(a[i] % x.first != 0){ flag = 0; break; } int ans = 0; while(a[i] % x.first == 0){ a[i] /= x.first; ans++; } mn = max(mn,(x.second - 1) / ans + 1); } if(flag == 0) continue; if(num == -1){ num = mn; }else{ num = min(num,mn); } } cout << num << '\n';}
signed main( ){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); init(); int t = 1;// cin>>t; while(t--) sl(); return 0;}