A.小红的同余
题意
给一个奇数m,请你找出一个数 x x x ( 0 ≤ x < m 0 \le x < m 0≤x<m) 使得 2 x ≡ 1 ( m o d m ) 2x \equiv 1 (mod\ m) 2x≡1(mod m)
思路
2 x ≡ 1 ( m o d m ) 2x \equiv 1(mod \ m) 2x≡1(mod m) 即 2 x 2x 2x 取余m等于1. 那么由于m是奇数, 很容易想到一个方案 2 x = m + 1 2x = m+1 2x=m+1 , 即 x = m + 1 2 x = \frac{m+1}{2} x=2m+1
代码
#include<bits/stdc++.h>
using namespace std;
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define int long long
#define rep(i,l,r) for(int i = l;i<=r;i++)
#define per(i,r,l) for(int i = r;i>=l;i--)
const int INF = 0x3f3f3f3f3f3f3f3f;
typedef pair<int,int> PII;
void solve(){
int m;
cin>>m;
cout<<(m+1)/2;
}
signed main(){
int T = 1;
// cin>>T;
while(T--){
solve();
}
return 0;
}
B.小红的三倍数
题意
给n个数,问是否存在一种方案,使得 这n个数拼接之后是3的倍数。
思路
这里要用到一个数学知识,即x是3的倍数等价于 x的每一位相加的结果是3的倍数。
如123
,按位相加后$1+2+3 = 6 ,6 % 3 == 0 $ 于是123
是3的倍数。
所以我们不需要关心拼接的方案,只需要将每个数按位加和。 判断最终的总和是不是3的倍数即可。
代码
#include<bits/stdc++.h>
using namespace std;
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define int long long
#define rep(i,l,r) for(int i = l;i<=r;i++)
#define per(i,r,l) for(int i = r;i>=l;i--)
const int INF = 0x3f3f3f3f3f3f3f3f;
typedef pair<int,int> PII;
void solve(){
int n;
cin>>n;
int ans =0;
rep(i,1,n){
string str;
cin>>str;
for(auto p : str){
ans += (p - '0');
}
}
if(ans%3 == 0) cout<<"YES\n";
else cout<<"NO\n";
}
signed main(){
int T = 1;
// cin>>T;
while(T--){
solve();
}
return 0;
}
C.小红充电
题意
题目中的题意就很好懂,我这边直接粘贴下来
思路
如果当前的电量x小于超级充电的门槛电量t。 那么我们直接开启超级快充直到充满即可
a n s = 100 − x c ( x ≤ t ) ans = \frac{100-x}{c}(x \le t) ans=c100−x(x≤t)
如果当前的电量x大于超级充电的门槛电量t。 那么我们有两个选择
- 使用普通充电,耗时 t 1 = 100 − x b t1 = \frac{100-x}{b} t1=b100−x
- 先玩游戏使得电量等于门槛电量t,然后开始超级快充 ,耗时 t 2 = x − t y + 100 − t c t2 = \frac{x-t}{y} + \frac{100-t}{c} t2=yx−t+c100−t
最终答案为 a n s = m i n ( t 1 , t 2 ) ans = min(t1,t2) ans=min(t1,t2)
代码
#include<bits/stdc++.h>
using namespace std;
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define int long long
#define rep(i,l,r) for(int i = l;i<=r;i++)
#define per(i,r,l) for(int i = r;i>=l;i--)
const int INF = 0x3f3f3f3f3f3f3f3f;
typedef pair<int,int> PII;
void solve(){
int x,y,t,a,b,c;
cin>>x>>y>>t>>a>>b>>c;
if(x <= t) {
printf("%.8lf",(100 - x+0.0)/c);}
else{
double ans1 = 0;
double ans2 = 0;
ans1 = (100.0-x)/b;
ans2 = (x-t+0.0)/y + (100.0-t)/c;
printf("%.8lf",min(ans1,ans2));
}
return ;
}
signed main(){
int T = 1;
// cin>>T;
while(T--){
solve();
}
return 0;
}
D. 小红的 gcd
题意
求 g c d ( a , b ) gcd(a,b) gcd(a,b) , 其中 1 ≤ a ≤ 1 0 1 0 6 , 1 ≤ b ≤ 1 0 9 1\le a \le 10^{10^6}, 1\le b \le 10^9 1≤a≤10106,1≤b≤109
思路
本题考察辗转相除法。 即 g c d ( a , b ) = g c d ( b , a % b ) gcd(a,b) = gcd(b,a\%b) gcd(a,b)=gcd(b,a%b)因此我们计算出 c = a % b c = a\%b c=a%b 之后, 再使用基本的 g c d gcd gcd就可以得出结果于是我们问题就变为了如何求 a % b a\%b a%b 。
我们设a一共有n位,每一位为 a 1 , a 2 , . . . , a n a_1,a_2,...,a_n a1,a2,...,an 。那么有 a = ( ( ( 0 + a 1 ) ∗ 10 + a 2 ) ∗ 10... ) + a n a = (((0+a_1)*10+a_2)*10...)+a_n a=(((0+a1)∗10+a2)∗10...)+an
于是 a % b = ( ( ( ( 0 + a 1 ) ∗ 10 % b + a 2 ) ∗ 10 % b . . . ) + a n ) % b a\%b = ((((0+a_1)*10\%b+a_2)*10\%b...)+a_n)\%b a%b=((((0+a1)∗10%b+a2)∗10%b...)+an)%b .这样就可以保证运算过程中的数据始终在 l o n g l o n g long\ long long long的范围内
代码
#include<bits/stdc++.h>
using namespace std;
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define int long long
#define rep(i,l,r) for(int i = l;i<=r;i++)
#define per(i,r,l) for(int i = r;i>=l;i--)
const int INF = 0x3f3f3f3f3f3f3f3f;
typedef pair<int,int> PII;
void solve(){
string a;
int b;
cin>>a>>b;
int aa = 0;
for(auto p : a){
aa = aa*10 + p - '0';
aa %= b;
}
cout<<__gcd(aa,b)<<endl;
}
signed main(){
int T = 1;
// cin>>T;
while(T--){
solve();
}
return 0;
}
E.小红走矩阵
题意
有一个 n ∗ n n*n n∗n 的矩阵,小红从 ( 1 , 1 ) (1,1) (1,1) 走到 ( n , n ) (n,n) (n,n) ,定义一条路径的权值为经过的所有点的最大值 . 请你找到权值最小的路径
思路
求某个东西的 最小的最大值 .考虑二分答案 .
我们假设要找一条权值不大于 k k k的路径 , 那么显然 , 所有大于 k k k的点我们都不能走 , 所以在本次check中 , 将所有大于k的点都视为障碍物,使用bfs检查是否能从起点走到重点 , 若能则代表 a n s ≤ k ans \le k ans≤k , 否则 a n s > k ans > k ans>k
代码
#include<bits/stdc++.h>
using namespace std;
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define int long long
#define rep(i,l,r) for(int i = l;i<=r;i++)
#define per(i,r,l) for(int i = r;i>=l;i--)
const int INF = 0x3f3f3f3f3f3f3f3f;
typedef pair<int,int> PII;
int n;
bool vis[505][505];
int nextx[4] = {
0,0,1,-1};
int nexty[4] = {
1,-1,0,0};
int mp[505][505];
bool check(int mid){
if(mp[1][1] > mid) return false;
memset(vis,0,sizeof(vis));
queue<PII> q;
q.push({
1,1});
vis[1][1] = true;
while(q.size()){
int x = q.front().first;
int y = q.front().second;
q.pop();
if(x == n && y == n) return true;
for(int i = 0;i<4;i++){
int nx = x + nextx[i];
int ny = y + nexty[i];
if(nx < 1 || nx > n || ny < 1 || ny > n || vis[nx][ny]) continue;
if(mp[nx][ny] > mid) continue;
vis[nx][ny] = true;
q.push({
nx,ny});
}
}
return false;
}
void solve(){
cin >> n;
for(int i =1;i<=n;i++){
for(int j = 1;j<=n;j++) cin>>mp[i][j];
}
int l = 1,r = 1e9+5;
while(l<r){
int mid = (l+r) >> 1;
if(check(mid)){
r = mid;
}else
l = mid+1;
}
cout<<l;
}
signed main(){
int T = 1;
// cin>>T;
while(T--){
solve();
}
return 0;
}
F.小红的数组
题意
给n个数 a 1 , a 2 , . . . , a n a_1,a_2,...,a_n a1,a2,...,an , 以及q组询问 , 每次询问两个参数 l , r l,r l,r , 问区间连续子段和的绝对值最大是多少 . 即有 l ≤ x ≤ y ≤ r l \le x \le y \le r l≤x≤y≤r , 求最大的 a b s ( a [ x ] + a [ x + 1 ] + . . . + a [ y ] ) abs(a[x] + a[x+1] +... + a[y]) abs(a[x]+a[x+1]+...+a[y]) 是多少
思路
先对a数组进行求前缀和, s [ i ] = ∑ j = 1 i a [ j ] s[i] = \sum _{j=1}^i a[j] s[i]=∑j=1ia[j]
于是求 a b s ( a [ x ] + a [ x + 1 ] + . . . + a [ y ] ) abs(a[x]+a[x+1]+...+a[y]) abs(a[x]+a[x+1]+...+a[y]) 就等价于求 a b s ( s [ y ] − s [ x − 1 ] ) abs(s[y] - s[x-1]) abs(s[y]−s[x−1]) , 而题目规定 l ≤ x ≤ y ≤ r l \le x \le y \le r l≤x≤y≤r , 那么我们只需要找到 M A X i = l − 1 r s [ i ] MAX_{i=l-1}^r s[i] MAXi=l−1rs[i] , 以及 M I N i = l − 1 r s [ i ] MIN_{i=l-1}^r s[i] MINi=l−1rs[i] , 二者进行相减即可得出答案。
对于求区间最大/最小值问题, 我们使用ST表即可。
注意使用cin和cout可能会超时,需要关闭IO同流。
代码
#include<bits/stdc++.h>
using namespace std;
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define int long long
#define rep(i,l,r) for(int i = l;i<=r;i++)
#define per(i,r,l) for(int i = r;i>=l;i--)
const int INF = 0x3f3f3f3f3f3f3f3f;
typedef pair<int,int> PII;
int lg[500005];
int n;
int a[500005];
int f1[500005][30];
int f2[500005][30];
void init(){
lg[1] = 0;
rep(i,2,500003) lg[i] = lg[i>>1]+1;
rep(i,1,n) {
f1[i][0] = a[i];
f2[i][0] = a[i];
}
for(int j = 1;j<=lg[n+1];j++){
for(int i = 0;i <= n-(1<<j)+1;i++){
f1[i][j] = max(f1[i][j-1],f1[i+(1<<(j-1))][j-1]);
f2[i][j] = min(f2[i][j-1],f2[i+(1<<(j-1))][j-1]);
}
}
}
void solve(){
cin>>n;
for(int i = 1;i<=n;i++){
cin>>a[i];
a[i] += a[i-1];
}
init();
int q;
cin>>q;
while(q--){
int l, r;
cin>>l>>r;
l--;
int log = lg[r-l+1];
int ans = \
max(f1[l][log],f1[r-(1<<log)+1][log])- \
min(f2[l][log],f2[r-(1<<log)+1][log]);
cout<<ans<<'\n';
}
}
signed main(){
IO;
int T = 1;
// cin>>T;
while(T--){
solve();
}
return 0;
}