CSP-S 模拟赛 #2 题解

300 rk3。题面是本校 OJ 的,链接挂了找我。

upd: T1 被 xiaopanda 的 hack 数据卡了,T3 数据有误,赛后重测 xiaopanda AK了。

T1-A-B

Problem

出题是一件痛苦的事情!

题目看多了也有审美疲劳,于是我舍弃了大家所熟悉的 A+B Problem,改用 A-B 了哈哈!

好吧,题目是这样的:给出一串数以及一个数字 \(C\) ,要求计算出所有 \(A-B=C\) 的数对的个数。(不同位置的数字一样的数对算不同的数对)。

输入格式

第一行包括2个非负整数 \(N\)\(C\),中间用空格隔开。
第二行有 \(N\) 个整数,中间用空格隔开,作为要求处理的那串数。

输出格式

输出一行,表示该串数中包含的所有满足 \(A-B=C\) 的数对的个数。

Input

4 1
1 1 2 3

Output

3

\(1\le N\le 2\times 10^5\)

Solution

签到,用个 map 瞎几把乱搞就可以了。
hack: \(c=0\),算答案会被加两遍,减掉即可。

#include<bits/stdc++.h>
#define int long long
using namespace std;
inline void read(int &x)
{
	char ch=getchar();
	int r=0,w=1;
	while(!isdigit(ch))w=ch=='-'?-1:1,ch=getchar();
	while(isdigit(ch))r=(r<<3)+(r<<1)+(ch^48),ch=getchar();
	x=r*w;
}
map<int,int>mp;
const int N=1e6+7;
int a[N];
main()
{
	freopen("a-b.in","r",stdin);
	freopen("a-b.out","w",stdout);
	int n,c,ans=0;
	read(n);read(c);
	for(int i=1;i<=n;i++)
		read(a[i]),mp[a[i]]++;
	for(int i=1;i<=n;i++)
		ans+=mp[a[i]+c]-(c==0);
	cout<<ans;
	return 0;
}

T2-吉波那契数列

题面

Solution

先表示 \(G_i\):
\(G_0=1,G_1=t,G_2=t+1,G_3=2t+1,G_4=3t+2,G_5=5t+3\)

那么对于斐波那契 \(F={0,1,1,2,3,5...}\) (下标从 \(0\) 开始),有
\(G_i=F_it+F_{i-1}(i>0)\),所以只要预处理出斐波那契数列,直接解方程看是否满足条件。

#include<bits/stdc++.h>
#define int long long
using namespace std;
void read(int &x)
{
	char ch=getchar();
	int r=0,w=1;
	while(!isdigit(ch))w=ch=='-'?-1:1,ch=getchar();
	while(isdigit(ch))r=(r<<3)+(r<<1)+(ch^48),ch=getchar();
	x=r*w;
}
const int N=5e6+7,mod=19960515;
int f[N];
void solve(){
	int x,k,y;
	read(x);read(k);read(y);
	int t=(k-f[x-1])/f[x];
	if(t*f[x]!=k-f[x-1]||t<=0){puts("-1");return;}
	printf("%lld\n",(f[y]*t%mod+f[y-1])%mod);
}
main()
{
	freopen("gibonacci.in","r",stdin);
	freopen("gibonacci.out","w",stdout);
	f[0]=0;f[1]=1;
	for(int i=2;i<=5e6;i++)
		f[i]=f[i-1]+f[i-2],f[i]%=mod;
	int T;
	read(T);
	while(T--)solve();
	return 0;
}

T3-魔塔

题面

Solution

测试时因不明原因写挂而爆0。

考虑到数据规模较小,设 \(f(x,y,h,ans)\) 表示在 \((x,y)\) 剩余 \(h\) 体力,打过 \(ans\) 个怪,直接记忆化搜索即可,注意合理剪枝。

std 超级压行版:

#include<cstdio>
int h,n,m,tim,ans,x,y,i,j;char a[10][10],v[10][10][10][10];
int dx[]={-1,0,0,1},dy[]={0,-1,1,0};
int check(int x,int y){return x>=0&&x<n&&y>=0&&y<m;}
void dfs(int x,int y,int h,int k){
	if(v[x][y][h][k]==tim)return;v[x][y][h][k]=tim;
	for(int nx,ny,i=0;i<4;i++)
	if(check(nx=x+dx[i],ny=y+dy[i]))
	if(a[nx][ny]=='.')dfs(nx,ny,h,k);
	else if(a[nx][ny]=='E'){if(ans>k)ans=k;return;}
	else if(a[nx][ny]=='C')a[nx][ny]='.',dfs(nx,ny,h+5,k),a[nx][ny]='C';
	else if(a[nx][ny]=='M'&&h>0)a[nx][ny]='.',dfs(nx,ny,h-1,k+1),a[nx][ny]='M';
}
int main(){
	freopen("tower.in","r",stdin);
	freopen("tower.out","w",stdout);
	while(~scanf("%d%d%d\n",&h,&n,&m)){
		for(i=0,++tim;i<n;i++)scanf("%s",a[i]);
		for(i=0;i<n;i++)
		for(j=0;j<m;j++)
		if(a[i][j]=='S')x=i,y=j,a[i][j]=0;
		ans=233,dfs(x,y,h,0);
		if(ans==233)puts("Poor Warrior");
		else printf("%d\n",ans);
	}
}

return 0 CCF 那里会爆0的(。

T4-对战

题面

Solution

题目要求裁判水平要在两人之间,那个什么路程条件就是说选的裁判的下标也要在两人之间,即选择 \(i<k<j\) 满足 \(a_i<a_k<a_j\)\(a_i>a_k>a_j\)

考虑枚举裁判,如果我们知道他左边有几个比他小,右边有几个比他大,根据乘法原理即可求出答案,这个用树状数组维护值域即可(逆序对都会叭)。最后把两种情况相加。

代码的变量应该都看得懂。

#include<bits/stdc++.h>
#define int long long
using namespace std;
void read(int &x)
{
	char ch=getchar();
	int r=0,w=1;
	while(!isdigit(ch))w=ch=='-'?-1:1,ch=getchar();
	while(isdigit(ch))r=(r<<3)+(r<<1)+(ch^48),ch=getchar();
	x=r*w;
}
const int N=1e6+7;
int a[N],n,lmx[N],rmx[N],lmn[N],rmn[N],c[N],mx;
int lowbit(int x){return x&-x;}
void add(int x,int k){
	while(x<=mx){
		c[x]+=k;
		x+=lowbit(x);
	}
}
int query(int x){
	int sum=0;
	while(x>=1){
		sum+=c[x];
		x-=lowbit(x);
	}
	return sum;
}
void clear(){memset(c,0,sizeof c);}
void solve(){
	read(n);mx=-1;
	for(int i=1;i<=n;i++)read(a[i]),mx=max(mx,a[i]);
	clear();
	for(int i=1;i<=n;i++){
		lmn[i]=query(a[i]-1);
		lmx[i]=i-1-lmn[i];
		add(a[i],1);
	}
	clear();
	for(int i=n;i>=1;i--){
		rmn[i]=query(a[i]-1);
		rmx[i]=n-i-rmn[i];
		add(a[i],1);
	}
	int ans=0;
	for(int i=1;i<=n;i++)
		ans+=lmn[i]*rmx[i]+lmx[i]*rmn[i];
	printf("%lld\n",ans);
}
main()
{
	freopen("inhouse.in","r",stdin);
	freopen("inhouse.out","w",stdout);
	int T;
	read(T);
	while(T--)solve();
	return 0;
}
posted @ 2022-10-05 15:32  Epoch_L  阅读(69)  评论(1编辑  收藏  举报