A. 学习求余

数学。

我们都知道,想要两个数的积越大,那么这两个数的差就要越小,所以想要qq尽可能大,那么kk也要尽可能大,那么中间的数就是最好的选择,但若是偶数会整除,所以要加11,若是奇数那就找正中间,那qq就是nkn-k;举个例子,若nn100100,那么qq4949kk5151,若nn101101,那么qq5050kk5151

#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. 提取数字

字符串。

没有想到前导零不要考虑的情况,所以只拿了7070分,所以下一次一定要好好审题!

这道题目我们可以在遇到数字的时候遍历一下,直到是字母的时候再将现在的数字加上去再加55,最后输出答案即可。

注意:这道题目要开longlong longlong

#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. 武器选择

前缀和。

这道题本来写了个暴力的,但是没有注意aia_i的数据范围,所以RE了,下次一定要注意数据范围。

首先我们要明白,因为当你第aia_i次遇到代号为aia_i的武器时,才能够获得这把武器,所以武器至多能领到sqrt(n)sqrt(n)个,那么ai>na_i>n的就要初次被筛选掉了;其次,我们要用一个数组来记录每个武器被领到了几次,若cnti>icnt_i>i(假设这个数组为cntcnt),那么也要被筛掉。然后用一个数组继续记录。但是!题目说是一个区间,所以要用一个前缀和数组来记录[1[1~n]n]每次分别有几个武器。在后面遍历mm次时,前缀和数组就要派上用场了,只要(fi,rfi,l1)>=bi(f_{i,r}-f_{i,l-1})>=b_i(假设前缀和数组为ff,第二次的记录数组为bb),那么就要用一个记录有几个数符合要求的变量+1+1了,最后输出kksumsum的组合数即可(假设记录有几个数符合要求的变量为sumsum)。

#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;
}