目录
New String
大意
给你26个字母,代表这些字母的优先级,然后给你一些字符串,让你根据给定的优先级给这些字符串排序,然后输出第k个字符串
注意这个题目中给定的两个排序条件,要按顺序来
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <map>
#include <string>
#include <cstring>
#include <cmath>
#include <stack>
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define fast ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define sc(a) scanf("%lld",&a)
#define pf(a) printf("%d",a)
#define endl "\n"
#define int long long
#define mem(a,b) memset(a,b,sizeof a)
#define ull unsigned long long
#define INF 0x3f3f3f3f3f3f3f3f
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(auto i=a;i<=b;++i)
#define bep(i,a,b) for(auto i=a;i>=b;--i)
#define LL long long
#define lowbit(x) x&(-x)
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define PI acos(-1)
#define pb push_back
#define x first
#define y second
const double eps = 1e-6;
const int mod = 998244353;
const int MOD = 1e9 + 7;
int n, k;
map<char, int> mp;//比较大小
string v[1010];
bool cmp(string s1, string s2)
{
int a = s1.size();
int b = s2.size();
for(int i = 0, j = 0; i < a && j < b; i++, j++)
{
if(mp[s1[i]] < mp[s2[j]]) return true;
else if(mp[s1[i]] > mp[s2[j]]) return false;
}
if(a < b)return true;
return false;
}
signed main()
{
fast;
string s;
cin >> s;
for(int i=0; i<26; i++)
{
mp[s[i]] = i;
}
cin >> n;
for(int i = 1; i <= n; i++)
cin >> v[i];
cin >> k;
sort(v + 1, v + n + 1, cmp);
cout << v[k] << endl;
}
/*
acbdefghijklmnopqrstuvwxyz
1
abcd
1
*/
C - Easy Problem
Easy Problem
也是个水题,但是比赛的时候读了假题,没做出来
大意
就说有两个人,从两个位置出发,俩人的移动是一样的,但是如果下一步要超过或者下一步是障碍物,就不动,问你最少几步就可以到一起,或者不能到一起
bfs直接乱杀
#include<bits/stdc++.h>
using namespace std;
const int N = 55;
char mp[N][N];
int vis[N][N][N][N];
int dist[N][N][N][N];
struct node
{
int xa, ya;
int xb, yb;
};
int n;
int dx[] = {0, 0, 0, 1, -1};
int dy[] = {0, 1, -1, 0, 0};
queue<node> q;
bool judge(int x,int y)
{
if(x < 1 || x > n || y < 1 || y > n || mp[x][y]=='*')
return false;
return true;
}
///*
void bfs(int x1, int y1, int x2, int y2)
{
memset(vis, 0x3f, sizeof vis);
q.push({x1, y1, x2, y2});
vis[x1][y1][x2][y2] = 0;
while(q.size())
{
node t = q.front();
q.pop();
if(t.xa == t.xb && t.ya == t.yb)
{
cout << vis[t.xa][t.ya][t.xb][t.yb] << endl;
return ;
}
for(int i=1; i<=4; i++)
{
int xxa = t.xa + dx[i], yya = t.ya + dy[i], xxb = t.xb + dx[i], yyb = t.yb + dy[i];
if(mp[xxa][yya] == '*' && mp[xxb][yyb] == '*') continue;
if(!judge(xxa, yya)) {xxa -= dx[i]; yya -= dy[i];}
if(!judge(xxb, yyb)) {xxb -= dx[i]; yyb -= dy[i];}
if(vis[xxa][yya][xxb][yyb] > vis[t.xa][t.ya][t.xb][t.yb] + 1)
{
vis[xxa][yya][xxb][yyb] = vis[t.xa][t.ya][t.xb][t.yb] + 1;
q.push({xxa, yya, xxb, yyb});
}
}
}
puts("no solution");
}
//*/
int main()
{
cin >> n;
int x1, y1, x2, y2;
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
{
cin >> mp[i][j];
if(mp[i][j] == 'a') x1 = i, y1 = j;
if(mp[i][j] == 'b') x2 = i, y2 = j;
}
bfs(x1, y1, x2, y2);
return 0;
}
I - 250-like Number
大意
定义 k=p× q 3 q^3 q3 并且p和q都是质数,这样的k就是类似250的数,问n以内这样的数有多少
思路很好想,我一开始想直接用pow开个立方,然后发现精度误差还挺大,最后少算了不少数,然后决定,用相乘起来跟n比较,就是你筛出来质数,枚举p或者q,然后求就行,我这里枚举q,因为我感觉这样好做
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <map>
#include <string>
#include <cstring>
#include <cmath>
#include <stack>
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define fast ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define sc(a) scanf("%lld",&a)
#define pf(a) printf("%d",a)
#define endl "\n"
#define int long long
#define mem(a,b) memset(a,b,sizeof a)
#define ull unsigned long long
#define INF 0x3f3f3f3f3f3f3f3f
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(auto i=a;i<=b;++i)
#define bep(i,a,b) for(auto i=a;i>=b;--i)
#define LL long long
#define lowbit(x) x&(-x)
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define PI acos(-1)
#define pb push_back
#define x first
#define y second
const double eps = 1e-6;
const int mod = 998244353;
const int MOD = 1e9 + 7;
const int N = 8e6;
int primes[N], cnt; // primes[]存储所有素数
bool st[N]; // st[x]存储x是否被筛掉
void get_primes(int n)
{
for (int i = 2; i <= n; i ++ )
{
if (!st[i]) primes[++ cnt] = i;
for (int j = 1; primes[j] <= n / i; j ++ )
{
st[primes[j] * i] = true;
if (i % primes[j] == 0) break;
}
}
}
signed main()
{
int n; cin >> n;
int res = 0;
get_primes(8e6);
for(int i = 1; i <= cnt; i++)
{
int l = 0, r = i - 1;
int nn = primes[i] * primes[i] * primes[i];
if (nn > n) break;
while (l < r)
{
int mid = l + r + 1 >> 1;
if (nn <= n / primes[mid]) l = mid;
else r = mid - 1;
}
res += l;
}
cout << res << endl;
return 0;
}
E - Prefix Equality
大意就是,给你两个序列,给你两个数,让你看看每个序列前那些数里面的数构成的集合是不是一样的,集合有互异性
做法,一个小哈希,把每个数弄得不同加一块,然后扔一个数组里面存着就行
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <map>
#include <string>
#include <cstring>
#include <cmath>
#include <stack>
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define fast ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define sc(a) scanf("%lld",&a)
#define pf(a) printf("%d",a)
#define endl "\n"
#define int long long
#define mem(a,b) memset(a,b,sizeof a)
#define ull unsigned long long
#define INF 0x3f3f3f3f3f3f3f3f
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(auto i=a;i<=b;++i)
#define bep(i,a,b) for(auto i=a;i>=b;--i)
#define LL long long
#define lowbit(x) x&(-x)
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define PI acos(-1)
#define pb push_back
#define x first
#define y second
const double eps = 1e-6;
const int mod = 998244353;
const int MOD = 1e9 + 7;
const int N = 2e5 + 10;
typedef unsigned long long ULL;
int P = 131;
ULL p; // h[k]存储字符串前k个字母的哈希值, p[k]存储 P^k mod 2^64
ULL a[N], b[N];
set<int> st;
signed main()
{
int n, x; cin >> n;
for (int i = 1; i <= n; i ++ )
{
cin >> x;
if(st.count(x)) a[i] = a[i - 1];
else
{
a[i] = a[i - 1] + x * (x + P);
st.insert(x);
}
}
// cout << endl;
st.clear();
// p = 0;
for (int i = 1; i <= n; i ++ )
{
cin >> x;
if(st.count(x)) b[i] = b[i - 1];
else
{
b[i] = b[i - 1] + x * (x + P);
st.insert(x);
}
}
// puts("");
int m; cin >> m;
int l, r;
while(m --)
{
cin >> l >> r;
if(a[l] == b[r]) puts("Yes");
else puts("No");
}
return 0;
}
K - Endless Walk
算是个结论吧
这个题大意就是,让你找出来图中好点的个数,好点的定义就是你能从这个点,走到一个环上,注意,这个图是有向图,保证没有重边
实际上就是反向建图然后跑一个拓扑序,至于怎么证明,可以这样想,拓扑图肯定不会走到环上,然后反向建图就是把走不到环上的点都找出来了,用所有的点减去这些点就对了
实在想不出来可以自己画一画
引用其他博客的话:
实际上就是找从1号点开始到环(包括环)的路径上所包含的所有点。我们知道在找拓扑排序的时候是找当前入度为0的点,由此可知在找拓扑排序的过程中,环是永远不会被遍历到的(环的起始点的入度不可能为0),同时不会被遍历到的还有不在从起点到环路径上的除环以外且与环相连的其他点。因此我们要存一个原图的反图,从反图的起点开始找拓扑序列(其实已经不是严格意义上的拓扑序列了,只是便于理解这样称呼),凡是能够遍历到的点,一定不在从原图1号点到环的路径上,而没有遍历到的点,则一定在从原图1号点到环的路径上,也就是我们所要求的答案。
原文链接:https://blog.csdn.net/qq_42883649/article/details/123801622
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define IOS std::ios::sync_with_stdio(false);std::cin.tie(0);
const int N = 2e5 + 10, M = 2e5 + 10;
vector<int> v[N];
int n, m;
int in[N];
int main()
{
// IOS
cin >> n >> m;
int ans = n;
int a, b;
for(int i=1; i<=m; i++)
{
cin >> a >> b;
v[b].push_back(a);
in[a] ++;
}
queue<int> q;
for(int i=1; i<=n; i++)
if(in[i] == 0)
{
q.push(i);
// ans --;
}
while(q.size())
{
ans --;
int t = q.front();
// cout << t << endl;
q.pop();
for(auto i : v[t])
{
in[i] --;
if(in[i] == 0)
{
q.push(i);
// ans --;
}
}
}
cout << ans << endl;
return 0;
}
J - Wrapping Chocolate
Wrapping Chocolate
给你n个巧克力,m个盒子,问能不能都装进去,盒子和巧克力的长宽都给你,保证盒子大于等于巧克力数,问你巧克力能不能都装进去
贪心,从小往大贪心比较困难,那我们就可以换个思路,从大往小贪心,先对盒子和巧克力进行排序,我这里按照自己的代码讲,就是先把盒子和巧克力按照长和宽进行相同的排序,然后从最后一个巧克力开始,找到最适合这个巧克力的盒子,说白了就是我要找比这个巧克力大的,最小的盒子!怎么找呢,二分,这里还可以用个multiset,用来找到比这个巧克力大的盒子,我这里是按照长度先排序的,也就是,我要找到,大于等于这个巧克力长度的所有的宽,都扔进multiset里面,然后二分巧克力长度就OK了,如果有不符合的,因为我们这个是从大往小找,就可以直接确定,往后长度都比它小,所以一定不能都装进去,直接退出就行
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <map>
#include <string>
#include <cstring>
#include <cmath>
#include <stack>
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define fast ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define sc(a) scanf("%lld",&a)
#define pf(a) printf("%d",a)
#define endl "\n"
#define int long long
#define mem(a,b) memset(a,b,sizeof a)
#define ull unsigned long long
#define INF 0x3f3f3f3f3f3f3f3f
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(auto i=a;i<=b;++i)
#define bep(i,a,b) for(auto i=a;i>=b;--i)
#define LL long long
#define lowbit(x) x&(-x)
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define PI acos(-1)
#define pb push_back
#define x first
#define y second
const double eps = 1e-6;
const int mod = 998244353;
const int MOD = 1e9 + 7;
const int N = 2e5 + 10;
PII a[N], b[N];
int n, m;
multiset<int> s;
bool cmp(PII a, PII b)
{
if(a.x != b.x) return a.x < b.x;
else return a.y < b.y;
}
signed main()
{
// fast;
cin >> n >> m;
for(int i=1; i<=n; i++) cin >> a[i].x;
for(int i=1; i<=n; i++) cin >> a[i].y;
for(int i=1; i<=m; i++) cin >> b[i].x;
for(int i=1; i<=m; i++) cin >> b[i].y;
sort(a + 1, a + 1 + n, cmp);
sort(b + 1, b + 1 + m, cmp);
for(int i=n, j=m; i>=1; i--)
{
while(j >=1 && b[j].x >= a[i].x)
{
s.insert(b[j].y);
j --;
}
auto t = s.lower_bound(a[i].y);
if(t == s.end())
{
puts("No");
return 0;
}
else s.erase(t);
}
puts("Yes");
return 0;
}
G - Optimal Biking Strategy
G - Optimal Biking Strategy
动态规划
大意
就说一个人从家开始往一个商店走,中途有几个自行车站点,它可以并且只能在自行车站骑车放车,问你走路的最小是多少
标准dp,但是怎么推呢,感觉比较好想的就是,他肯定要从最后一站的能走的最远距离之内的最远的站骑过来,所以我们可以规定一下状态f[i][j]表示走到第i个车站,最大花j元需要走多少路
然后怎么找最远的站,当然是二分啦
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <map>
#include <string>
#include <cstring>
#include <cmath>
#include <stack>
#include<bitsdc++.h>
using namespace std;
#define ll long long
#define fast ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define sc(a) scanf("%lld",&a)
#define pf(a) printf("%d",a)
#define endl "\n"
#define int long long
#define mem(a,b) memset(a,b,sizeof a)
#define ull unsigned long long
#define INF 0x3f3f3f3f3f3f3f3f
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(auto i=a;i<=b;++i)
#define bep(i,a,b) for(auto i=a;i>=b;--i)
#define LL long long
#define lowbit(x) x&(-x)
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define PI acos(-1)
#define pb push_back
#define x first
#define y second
const double eps = 1e-6;
const int mod = 998244353;
const int MOD = 1e9 + 7;
const int N = 1e6 + 10;
int f[N][10];
int a[N];
int n,p,s,k;
signed main()
{
fast;
cin >> n >> p >> s;
for(int i=1;i<=n;i++) cin >> a[i];
cin >> k;
memset(f, 0x3f, sizeof f);
for(int i=0; i<=k; i++) f[0][i] = 0;//初始化,当在起点的时候,有多少钱也没走路
for(int i=1; i<=n; i++)
{
f[i][0] = f[i-1][0] + a[i] - a[i-1];//最多就走过去呗,就先弄上最大的
for(int j=1; j<=k; j++)//枚举有多少钱
{
f[i][j] = f[i-1][j] + a[i] - a[i-1];//最多就走过去呗,就先弄上最大的
for(int x=0; x<=j; x++)//枚举有多少钱时能走的距离
{
int dist = x * s;//能骑的距离
int l = 1, r = i - 1;
while(l < r)
{
int mid = (l + r) >> 1;
if(a[i] - a[mid] <= dist) r = mid;
else l = mid + 1;
}//这里要注意!!这个二分可能存在找不到答案的情况,因此要特判
//当l大于r的时候,可能是压根没二分,这时候就不能更细,比如1, 0
//如果 a[i] - a[r] > dist这时候也是无解,但是可能二分了,也要判断一下不能更新
if(l <= r && a[i] - a[r] <= dist) f[i][j]=min(f[i][j], f[r][j - x]);
}
}
}
int res = INF;
for(int i=1; i<=n; i++)
res = min(res, f[i][k] + p - a[i]);
cout << res << endl;
return 0;
}
D - Maximum Value
大意
给你一堆数,让你从这些数中找出来 a i a_i ai mod a j a_j aj 的最大值,保证 a i a_i ai >= a j a_j aj
想要取模最大,就得是模数的倍数-1这种,所以就枚举倍数,看看比每个数倍数小的最大值,取个模,然后跟最大值取个max,最后就是答案,数据在二分范围内,2e6是因为最大一个数可能是1e6
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <map>
#include <string>
#include <cstring>
#include <cmath>
#include <stack>
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define fast ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define sc(a) scanf("%lld",&a)
#define pf(a) printf("%d",a)
#define endl "\n"
#define int long long
#define mem(a,b) memset(a,b,sizeof a)
#define ull unsigned long long
#define INF 0x3f3f3f3f3f3f3f3f
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(auto i=a;i<=b;++i)
#define bep(i,a,b) for(auto i=a;i>=b;--i)
#define LL long long
#define lowbit(x) x&(-x)
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define PI acos(-1)
#define pb push_back
#define x first
#define y second
const double eps = 1e-6;
const int mod = 998244353;
const int MOD = 1e9 + 7;
vector<int> v; // 存储所有待离散化的值
int n;
signed main()
{
fast;
cin >> n;
int a;
for(int i=1; i<=n; i++)
{
cin >> a;
v.push_back(a);
}
sort(v.begin(), v.end()); // 将所有值排序
v.erase(unique(v.begin(), v.end()), v.end()); // 去掉重复元素
int res = 0;
for(int i=0; i<v.size(); i++)
{
for(int j=v[i] + v[i]; j<=2e6; j+=v[i])
{
int id = lower_bound(v.begin(), v.end(), j) - v.begin() - 1;//返回的下标减1就是比它小的最大的
if(id == -1) continue;
res = max(res, v[id] % v[i]);
}
}
cout << res << endl;
return 0;
}