CSP - S 2024 模拟赛3补题报告

C S P   −   S    2024   模拟赛 3   补题报告 2024 年 7 月 23 日 − 2023 年 7 月 25 日 b y    邓时飏 CSP \ - \ S \ \ 2024 \ \ 模拟赛3 \ \ 补题报告 \\ 2024年7月23日 - 2023年7月25日 \\ by \ \ \ 邓时飏 CSP  S  2024  模拟赛3  补题报告20247232023725by   邓时飏

一、做题情况

  • 第一题比赛 80 80 80 / 100 100 100 ,赛后通过

  • 第二题比赛 0 0 0 / 100 100 100 ,赛后通过

  • 第三题比赛 0 0 0 / 100 100 100 ,赛后通过

  • 第四题比赛 0 0 0 / 100 100 100 ,赛后通过

  • 比赛得分 0 0 0 / 400 400 400 ,赛后补题 400 400 400 / 400 400 400

二、题解报告

T1:

题面:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

做法:

枚举两个点,确定另外两个点。

附:AC代码
#include<bits/stdc++.h>
using namespace std;
int x[3005],y[3005],vis[5005][5005];
int main(){
	int n,maxn=0;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>x[i]>>y[i];
		vis[x[i]][y[i]]++;
	}
	for(int i=1;i<=n;i++)
		for(int j=i+1;j<=n;j++){
			double nx=(x[i]+x[j])/2.0,ny=(y[i]+y[j])/2.0;
			double a=nx-ny,b=nx+ny;
			if(a-int(a)!=0||b-int(b)!=0) continue;
			int dx=int(a)+y[i],dy=int(b)-x[i],xx=int(a)+y[j],yy=int(b)-x[j];
			if(dx<0||dy<0||xx<0||yy<0||dx>5000||dy>5000||xx>5000||yy>5000) continue;
			if(vis[dx][dy]&&vis[xx][yy]) maxn=max(maxn,int((dx-x[i])*(dx-x[i])+(dy-y[i])*(dy-y[i])));
		}	
	cout<<maxn;
	return 0;
}

T2:

题面:

在这里插入图片描述
在这里插入图片描述

做法:

求从一个序列中有序地取出k个数后的最大值,该值为每个数减去其前面所有数的绝对值之和。

首先对原序列排序。排序不影响答案。

接着,显然取出最大和最小值一定没错的。

再依次从没有取出的数中,取最小的和最大的放在取出的序列中间。

这个又为什么是对的呢?

考虑现在要取出的数放到取出的序列中间时,左右各有 l s i z e , r s i z e lsize,rsize lsize,rsize个数,左右数字和各为 l s u m , r s u m lsum,rsum lsum,rsum

那么插入这个数 x x x对答案的贡献为

( r s u m − r s i z e ∗ x ) + ( l s i z e ∗ s u m − l s u m ) (rsum-rsize*x)+(lsize*sum-lsum) (rsumrsizex)+(lsizesumlsum)
提取
( r s u m − l s u m ) − ( r s i z e − l s i z e ) ∗ x (rsum-lsum)-(rsize-lsize)*x (rsumlsum)(rsizelsize)x
这个式子同时解释了为什么整个取出序列必须时升序的,且要从最大值和最小值开始取数,以及为什么要尽量保持左右数的数的数量平均。

附:AC代码
#include <bits/stdc++.h>
#define IL inline
#define re register
#define LL long long
#define ULL unsigned long long
#define debug printf("Now is %d\n",__LINE__);
using namespace std;

template<class T>inline void read(T&x) {
	char ch=getchar();
	int fu;
	while(!isdigit(ch)&&ch!='-') ch=getchar();
	if(ch=='-') fu=-1,ch=getchar();
	x=ch-'0';
	ch=getchar();
	while(isdigit(ch)) {
		x=x*10+ch-'0';
		ch=getchar();
	}
	x*=fu;
}
inline int read() {
	int x=0,fu=1;
	char ch=getchar();
	while(!isdigit(ch)&&ch!='-') ch=getchar();
	if(ch=='-') fu=-1,ch=getchar();
	x=ch-'0';
	ch=getchar();
	while(isdigit(ch)) {
		x=x*10+ch-'0';
		ch=getchar();
	}
	return x*fu;
}
int G[55];
template<class T>inline void write(T x) {
	int g=0;
	if(x<0) x=-x,putchar('-');
	do {
		G[++g]=x%10;
		x/=10;
	} while(x);
	for(int i=g; i>=1; --i)putchar('0'+G[i]);
	putchar('\n');
}
LL a[1000010],ansxb[1000][1000],ans[1000],n;
int main() {
	n=read();
	for(int i=1; i<=n; i++) a[i]=read();
	sort(a+1,a+n+1);
	if(n<=5) {
		do {
			re LL now=0;
			for(re int i=1; i<=n; i++) {
				for(re int j=1; j<=i; j++) now+=abs(a[i]-a[j]);
				if(now>ans[i]) {
					ans[i]=now;
					for(int j=1; j<=i; j++) ansxb[i][j]=a[j];
				}
			}
		} while(next_permutation(a+1,a+n+1));
		for(re int i=1; i<=n; i++) cout<<ans[i]<<endl;
	} else {
		cout<<0<<endl;
		LL ans=a[n]-a[1];
		LL l=2,r=n-1,lsum=a[1],lsize=1,rsum=a[n],rsize=1;
		cout<<ans<<endl;
		for(re int i=3; i<=n; i++) {
			if(i&1) {
				ans+=rsum-rsize*a[l]-lsum+lsize*a[l];
				lsum+=a[l];
				lsize++;
				l++;
			} else {
				ans+=rsum-rsize*a[r]-lsum+lsize*a[r];
				rsum+=a[r];
				rsize++;
				r--;
			}
			write(ans);
		}
	}
	return 0;
}

T3:

题面:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

做法:

在这里插入图片描述

附:AC代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
const int P[11] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31};
int n, a[N], p[N], q[N];
int dp[1 << 11], g[1 << 11];
vector<int> vec[N];
int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	int test;
	cin >> test;
	while (test --) {
		for (int i = 1; i <= 1000; i++) vec[i].clear();
		cin >> n;
		for (int i = 1; i <= n; i++) {
			cin >> a[i];
			q[i] = a[i];
			p[i] = 0;
			for (int k = 0; k < 11; k++) {
				if (q[i] % P[k] == 0) {
					p[i] |= 1 << k;
					while (q[i] % P[k] == 0) q[i] /= P[k];
				}
			}
			vec[q[i]].push_back(i);
		}
		fill(dp + 1, dp + (1 << 11), -1);
		dp[0] = 0;
		for (int i: vec[1]) {
			copy(dp, dp + (1 << 11), g);
			for (int j = 0; j < (1 << 11); j++) {
				if (dp[j] != -1 && (j & p[i]) == 0) {
					auto &v = g[j | p[i]];
					v = max(v, dp[j] + 1);
				}
			}
			copy(g, g + (1 << 11), dp);
		}
		for (int k = 2; k <= 1000; k++) {
			if (vec[k].size()) {
				copy(dp, dp + (1 << 11), g);
				for (int i: vec[k]) {
					for (int j = 0; j < (1 << 11); j++) {
						if (dp[j] != -1 && (j & p[i]) == 0) {
							auto &v = g[j | p[i]];
							v = max(v, dp[j] + 1);
						}
					}
				}
				copy(g, g + (1 << 11), dp);
			}
		}
		int ans = 1;
		for (int i = 0; i < (1 << 11); i++) ans = max(ans, dp[i]);
		cout << ans << endl;
	}
	return 0;
}

T4:

题面:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

做法:

在这里插入图片描述

附:AC代码
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define int long long
using namespace std;
const int inf=0x3f3f3f3f;
const ll inff=0x3f3f3f3f3f3f3f3f;
const double PI=3.1415926535897932385;
const double ol=1e6+5;
const int N=1e7+5;
const int M=1e9+7;
const ull P=131;
const int mod=1e9+7;
const int MOD=1e9+7;
const double eps=1e-5;
int read() {
	int w = 0, h = 1;
	char ch = getchar();
	while (ch < '0' || ch > '9') {
		if (ch == '-')h = -h;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9') {
		w = w * 10 + ch - '0';
		ch = getchar();
	}
	return w * h;
}
void write(int x) {
	if (x > 9) write(x / 10);
	putchar(x % 10 + '0');
}
void writeln(int x) {
	write(x);
	puts("");
}
void writech(int x) {
	write(x);
	putchar(' ');
}
ll lowbit(ll x) {
	return x&-x;
}
ll gcd(ll a,ll b) {
	return b==0?a:gcd(b,a%b);
}
ll lcm(ll a,ll b) {
	return a/gcd(a,b)*b;
}
ll exgcd(ll a,ll b,ll &x,ll &y) {
	if(!b) {
		x=1,y=0;
		return a;
	}
	ll d=exgcd(b,a%b,y,x);
	y-=a/b*x;
	return d;
}
ll ksm(ll a,ll b,ll c) {
	ll sum=1;
	a%=c;
	while(b) {
		if(b&1)sum=sum*a%c;
		a=a*a%c;
		b>>=1;
	}
	return sum;
}
ll addm(ll a,ll b,ll c) {
	return (a%c+b%c)%c;
}
ll faddm(ll a,ll b) {
	return (((a%b)+b)%b);
}
ll fact[N],infact[N];
void init(ll n) {
	fact[0]=1;
	for(int i=1; i<=n; i++) fact[i]=(fact[i-1]*i)%mod;
	infact[n]=ksm(fact[n],mod-2,mod);
	for(int i=n-1; i>=0; i--) infact[i]=infact[i+1]*(i+1)%mod;
}
ll cmb( ll a , ll b ) {
	if(b>a) return 0 ;
	return (((fact[a]*infact[a-b])%mod)*infact[b])%mod ;
}
int a[N],v[N];
int inv(int x) {
	return ksm(x,M-2,M);
}
void solve() {
	int n,m,dmx=0;
	cin>>n>>m;
	init(N-1);
	for(int i=1; i<=n; i++) cin>>a[i];
	for(int i=2; i<=n; i++) dmx=max(dmx,a[i-1]-a[i]);
	for(int i=0; i<=dmx; i++) v[i]=ksm(m,i,M)*inv(ksm(m-1,i,M))%M;
	int ans=1;
	for(int i=1; i<=a[n]; i++) ans=ans*m%M;
	for(int i=n-1; i>=1; i--) {
		int d=a[i]-a[i+1],cnt=0;
		for(int j=0; j<=d; j++) {
			int k=cmb(a[i]-j-1,a[i+1]-1);
			cnt+=v[j]*k;
			cnt%=M;
		}
		cnt=cnt*ksm(m-1,d,M)%M;
		ans=ans*cnt%M;
	}
	cout<<ans<<"\n";
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int T=1;
	while(T--) solve();
}

四、赛后总结

提升实力,控制时间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值