依旧掉分场, 疯狂wa, 感觉越打越菜了....
A. 好字符串
题目描述
给你一个长度为 n 的字符串 s,如果一个小写字母为好字符,当且仅当该小写字母对应的大写字母和它同时在字符串 s 中出现 或者 同时不在字符串 s 中出现;而如果一个字符串为好字符串,当且仅当 26 个小写字母 ‘a’∼‘z’都是好字符。
现在想知道字符串 s 是否为好字符串。
输入描述:
第一行输入一个整数 n (1≦n≦100),表示字符串 s 的长度。
第二行输入一个长度为 n 的字符串 s,仅由大小写字母组成。
输出描述:
如果字符串 s 为好字符串,输出 YES,否则输出 NO。注意输出均为大写字母。
解题思路:用两个数组进行统计一下,大写一组, 小写一组, 然后顺次匹配一下
写完三题后,准备交了,第一题就wa了一次,应该是遍历去重后的a,遍历成原字符串s了
更简单直接的代码2的思路
#include<bits/stdc++.h>
using namespace std;
int main(){
int n; cin>>n;
string s; cin>>s;
sort(s.begin(),s.end());
int c=0;
set<int> a(s.begin(),s.end());
// cout<<a.size()<<endl;
if(((int)a.size())&1) { cout<<"NO"; return 0; }
unordered_map<char,int> mp; int cnt=0,cnt0=0;
for(auto& x:a){
if(x>='a'&&x<='z'&&mp.count((char)(x-32))){
cnt++;
}
mp[x]++;
}
// cout<<cnt<<endl;
int n0=a.size();
if(cnt==n0/2) cout<<"YES";
else cout<<"NO";
return 0;
}
#include <bits/stdc++.h>
using namespace std;
int main(){
int n; cin>>n;
string s; cin>>s;
bool a[26]={false};
bool b[26]={false};
for (char ch:s) {
if (ch>='a'&&ch<='z') {
a[ch-'a']=true;
} else {
b[ch-'A']=true;
}
}
for (int i=0;i<26;i++) {
if (a[i]!=b[i]) {
cout<<"NO"<<endl;
return 0;
}
}
cout<<"YES"<<endl;
return 0;
}
B. 平均数
题目描述
班上有 n 名同学,其中每位同学都有一个数值,但是每位同学并不会告诉你这个数值为多少,他们只会告诉你这个数值是否大于 / 等于 / 小于这 n 个数值的平均数,具体地:
若 ai=−1,表示第 i 名同学的数值小于平均数;
若 ai=0,表示第 i 名同学的数值等于平均数;
若 ai=1,表示第 i 名同学的数值大于平均数。
其中平均数指的是这 n 个数值的平均数值(保留小数点,不四舍五入),如{3,4,5,6} 的平均数为 3+4+5+64=4.5。
但是,它们其中,有些人可能会说谎,请你检查并判断:若给定的这 n 个数 ai 满足平均数的情况,则输出 YES,否则输出 NO。输入描述:
第一行输入一个整数 n (1≦n≦105),表示数组 a 的长度。
第二行输入 n 个整数 a1,a2,…,an(−1≦ai≦1),表示每一个同学的数字与平均数的关系。
输出描述:
如果给定的这 n 个数 ai 满足平均数的情况,则输出 YES,否则输出 NO。注意输出均为大写字母。
解题思路:题意就是一问一个人, 它回复你比平均数大, 还是比平均数小, 还是相等,
只要总体回复中有一个1和-1都有就行, 特殊的是全为0, 输出YES
#include<bits/stdc++.h>
using namespace std;
int main(){
int n; cin>>n;
vector<int> a(n); int num=0;
for(int i=0;i<n;i++){
cin>>a[i];
num+=a[i];
}
if(num==0) { cout<<"YES"; return 0; }
int cnt0=0,cnt1=0;
for(int i=0;i<n;i++){
if(a[i]>0) cnt0++;
else if(a[i]<0) cnt1++;
}
if(cnt0>0&&cnt1>0) cout<<"YES";
else cout<<"NO";
return 0;
}
// avg=4
// -1 0 1 1
C. 质数
题目描述
给你 q 次询问,每次询问给出两个整数 l,r,现在需要你将区间 [l,r][l,r][l,r] 内所有数分别放入两个集合 S1,S2 其中之一,最终需要满足:
∙S1,S2 两个集合都至少有一个数,并且满足 gcd(S1)=1 且 gcd(S2)≠1。
现在,对于每次询问,在满足上述条件的情况下,求出 ∣len(S1)−len(S2)∣ 的最小值,如果没有满足的情况,则输出 −1。注:若集合 S={3},则 gcd(S)=gcd(3)=3;若集合 S={6,9,12},则 gcd(S)=gcd(6,9,12)=3,其中 gcd 表示集合内所有数的最大公因数。
输入描述:
第一行输入一个整数 q (1≦q≦105),表示询问次数。
此后 q 行,第 i 行输入两个整数 li,ri(1≦li≦ri≦1018),表示第 i 次询问的区间。
输出描述:
对于每次询问,新起一行输出一个整数,表示 ∣len(S1)−len(S2)∣ 的最小值,如果没有满足的情况,则输出 −1。
解题思路:两个集合, 集合S1中元素互质, 集合S2中元素不互质
两个集合, 一个数不行的, 两个数, 一个是1,因为要连续, 所以另外一个数只能是2, 其他是不行的,
统计区间中偶数和奇数的个数,如果只有一个奇数,eg: 2 3 4,
当至少一个偶数和至少两个奇数, 奇数gcd为1,偶数gcd>1, 放到S1和S2中即可
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
int main(){
int q;
cin >> q;
while(q--){
ll l, r;
cin>>l>>r;
ll n=r-l+1;
if(n==1){
cout<<-1<<endl;
continue;
}
if(n == 2){
if(l==1&&r==2){
cout<<0<<endl;
} else {
cout<<-1<<endl;
}
continue;
}
ll z =(r/2)-((l-1)/2);
ll e =n-z;
if(e==1){
cout<<1<<endl;
continue;
}
if(z>=1&&e>=2){
int d = abs(e-z);
cout<<d<<endl;
continue;
}
cout<<-1<<endl;
}
return 0;
}
D . 众数
题目描述
给定一个长度为 n 的数组 a1,a2,…,an,现在你需要执行恰好一次如下操作:
,∙选择两个不同的位置 i,j (1≦i,j≦n; i≠j),ai变成的ai+1, aj变成 aj -1。
现在,我们想知道,对于每一种不同的操作方式后得到的新数组(不包含不操作的情况),它们的众数都会是什么。你需要将全部可能称为众数的数字去重后,从小到大依次输出。【名词解释】
一个数组的众数:指的是这个数在数组中的出现次数最多,如果有多个数出现次数最多,则这些数中最大的那个数是众数,如:{1,2,2,4} 的众数为 2, {3,3,2,2,1,1} 的众数为 3。输入描述:
第一行输入一个整数 n (2≦n≦103),表示数组的大小。
第二行输入 n 个整数 a1,a2,…,an(1≦ai≦10^6),表示数组的元素。
输出描述:
在一行上从小到大依次输出去重后的若干个整数,代表所有可能出现的众数。
解题思路:代码的时间复杂度是O(n^2 log n),
用一个set维护当前数字的出现次数, 如果出现次数相同就按数值大小进行降序处理,
然后对于每一组数据进行+1/-1的操作, 更新频率数组和相关的节点信息, 然后将当前众数添加到ans数组里面, 同时进行恢复操作
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int max_Num = 1e7 + 10;
struct Node{
int num, cnt;
bool operator<(const Node& other) const {
if (cnt == other.cnt) {
return num > other.num;
}
return cnt > other.cnt;
}
};
set<Node> st;
vector<int> fq(max_Num);
void o2(int x, int d) {
st.erase({x, fq[x]});
fq[x] += d;
st.insert({x, fq[x]});
}
void o1(int x, int d) {
o2(x, -1);
o2(x + d, 1);
}
set<int> ans;
int main() {
int n;
cin >> n;
vector<int> a(n + 1);
for (int i = 1; i <= n; i++) {
cin >> a[i];
fq[a[i]]++;
}
for (int i = 0; i < max_Num; i++) {
if (fq[i] != 0) {
st.insert({i, fq[i]});
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (i == j) {
continue;
}
o1(a[i], 1);
o1(a[j], -1);
ans.insert(st.begin()->num);
o1(a[i] + 1, -1);
o1(a[j] - 1, 1);
}
}
for (auto& x : ans) {
cout << x << " ";
}
cout << endl;
return 0;
}
E. 种类数
题目描述
给定一个长度为 n 的数组 a1,a2,…,an,定义一轮操作如下:
,∙令 x 为当前数组中所有数的种类数(即不同数的数量),随后对数组中的每一个元素都进行一次修改——对于每个索引 i (1≦i≦n),使得 ai 变为 max{0,ai−x}。
我们想知道,至少需要多少轮操作(可以为零轮),才能使得数组 a 中所有数变得相同。我们可以证明,有限次操作内一定可以达成目标。输入描述:
第一行输入一个整数 n (1≦n≦105),表示数组的长度。
第二行输入 n 个整数 a1,a2,…,an (0≦ai≦10^18),表示数组的元素。
输出描述:
输出一个整数,代表要使得数组 a 中所有数变得相同的最少操作轮数。
解题思路:我赛时的代码时间复杂度是O(nlogn)但是就是超时过不了,
用二分, 我们每轮减的是某一个符合条件的区间而不是一个数字
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main() {
int n;
cin >> n;
vector<ll> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
sort(a.begin(), a.end());
a.erase(unique(a.begin(), a.end()), a.end());
bool f = false;
for (ll x : a) {
if (x == 0) {
f = true;
break;
}
}
vector<ll> p;
for (ll x : a) {
if (x > 0) {
p.push_back(x);
}
}
if (p.empty()) {
cout << 0 << endl;
return 0;
}
ll ans = 0;
ll d = 0;
int st = 0; //指向数组中第一个未被完全减到 0 的数
n = a.size();
while (true) {
int k = n - st + (f ? 1 : 0);
if (k <= 1) {
break;
}
ll m = a[st] - d;
int x = k;
ll t = (m + x - 1) / x; //还需要几轮
ans += t;
d += x * t;
int nxt = upper_bound(a.begin() + st, a.end(), d) - a.begin();
if (nxt > st) {
st = nxt;
f = true;
}
}
cout << ans << endl;
return 0;
}
F. 中位数
解题思路:贡献法, 枚举中位数, 求mid =1 -> n 的乘积, 每个mid ^(mid在所有肯呢个排列中的所有可能区间中位数的情况数),枚举所有可能的区间长度 len=1, len=2, len=3....len=n
len! * len*(n-len) ! * ( n-len +1)
比mid小:mid-1 比mid大:n-mid
mid左侧为 C (len/2).floor / mid-1 ; mid右侧为 C len-1-(len/2).floor / n-mid
然后从len=1 -> n累加
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int P=1610612741;
const int PM1=P-1;
int Qpow(int a,int b){
int res=1;
while(b){
if(b&1) res=res*a%P;
a=a*a%P;
b>>=1;
}
return res;
}
void solve(){
int n;
cin>>n;
vector<vector<int>> C(n+1,vector<int>(n+1));
for(int i=0;i<=n;i++){
C[i][0]=1;
for(int j=1;j<=i;j++){
C[i][j]=(C[i-1][j]+C[i-1][j-1])%PM1;
}
}
vector<int> f(n+1);
f[0]=1;
for(int i=1;i<=n;i++){
f[i]=1LL*f[i-1]*i%PM1;
}
//预处理
vector<int> ff(n+1);
for(int i=1;i<=n;i++){
ff[i]=1LL*f[i]*f[n-1]%PM1;
ff[i]=1LL*ff[i]*(n-i+1)%PM1;
}
int ans=1;
for(int i=2;i<=n;i++){
int tot=0;
for(int l=1;l<=n;l++){
int c=0;
if(l%2==0){
c=1LL*C[i-1][l/2]*C[n-i][l/2-1]%PM1;
}else{
c=1LL*C[i-1][l/2]*C[n-i][l/2]%PM1;
}
tot+=1LL*c*ff[l]%PM1;
}
ans=1LL*ans*Qpow(i,tot%PM1)%P;
}
cout<<ans<<endl;
}
signed main(){
solve();
return 0;
}
感谢大家的点赞和关注,你们的支持是我创作的动力!