- 吴易繁 的博客
国庆模拟赛DAY01
- @ 2024-10-2 19:06:12
A. 学习求余
数学。
我们都知道,想要两个数的积越大,那么这两个数的差就要越小,所以想要尽可能大,那么也要尽可能大,那么中间的数就是最好的选择,但若是偶数会整除,所以要加,若是奇数那就找正中间,那就是;举个例子,若是,那么是,是,若是,那么是,是。
#include<bits/stdc++.h>
using namespace std;
int main(){
freopen("mod.in","r",stdin);
freopen("mod.out","w",stdout);
long long n;
cin>>n;
long long t=n/2+1;
cout<<t*(n%t);
return 0;
}
B. 提取数字
字符串。
没有想到前导零不要考虑的情况,所以只拿了分,所以下一次一定要好好审题!
这道题目我们可以在遇到数字的时候遍历一下,直到是字母的时候再将现在的数字加上去再加,最后输出答案即可。
注意:这道题目要开 。
#include<bits/stdc++.h>
#define int long long
using namespace std;
signed main
freopen("number.in","r",stdin);
freopen("number.out","w",stdout);
int n;
int sum=0;
cin>>n;
string s;
cin>>s;
for(int i=0;i<=s.size();i++){
if(s[i]>='0'&&s[i]<='9'){
int ans=0;
while(s[i]>='0'&&s[i]<='9'){
ans=ans*10+(s[i]-'0');
i++;
}
sum+=ans+5;
}
}
cout<<sum;
return 0;
}
C. 武器选择
前缀和。
这道题本来写了个暴力的,但是没有注意的数据范围,所以RE了,下次一定要注意数据范围。
首先我们要明白,因为当你第次遇到代号为的武器时,才能够获得这把武器,所以武器至多能领到个,那么的就要初次被筛选掉了;其次,我们要用一个数组来记录每个武器被领到了几次,若(假设这个数组为),那么也要被筛掉。然后用一个数组继续记录。但是!题目说是一个区间,所以要用一个前缀和数组来记录~每次分别有几个武器。在后面遍历次时,前缀和数组就要派上用场了,只要(假设前缀和数组为,第二次的记录数组为),那么就要用一个记录有几个数符合要求的变量了,最后输出和的组合数即可(假设记录有几个数符合要求的变量为)。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
long long a[N],b[N],c[N][10],cnt[N],flag[N];
int f[500][N];
int main(){
freopen("wq.in","r",stdin);
freopen("wq.out","w",stdout);
int n,idx=0;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
if(a[i]<=n) cnt[a[i]]++;
}
for(int i=1;i<=n;i++){
if(cnt[i]>=i){
b[++idx]=i;
for(int j=1;j<=n;j++) f[idx][j]=f[idx][j-1]+(a[j]==i);
}
c[i][1]=i;
if(i>=2) c[i][2]=i*(i-1)/2;
if(i>=3) c[i][3]=i*(i-1)*(i-2)/6;
if(i>=4) c[i][4]=i*(i-1)*(i-2)*(i-3)/24;
}
int m;
cin>>m;
while(m--){
int l,r,k;
cin>>l>>r>>k;
int cnt=0;
for(int i=1;i<=idx;i++) if((f[i][r]-f[i][l-1])>=b[i]) cnt++;
cout<<c[cnt][k]<<endl;
}
return 0;
}