CSP - S 2023 模拟赛2补题报告

C S P   −   S    2024   模拟赛 2   补题报告 2023 年 7 月 21 日 − 2024 年 7 月 21 日 b y    邓时飏 CSP \ - \ S \ \ 2024 \ \ 模拟赛2 \ \ 补题报告 \\ 2023年7月21日 - 2024年7月21日 \\ by \ \ \ 邓时飏 CSP  S  2024  模拟赛2  补题报告20237212024721by   邓时飏

一、做题情况

  • 第一题比赛 30 30 30 / 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:

题面:
题目描述
给你一个长度为N的正整数序列,如果一个连续的子序列,子序列的和能够被K整
除,那么就视此子序列合法,求原序列包括多少个合法的连续子序列?
对于一个长度为8的序列,K=4的情况:2, 1, 2, 1, 1, 2, 1, 2 。它的答案为6,子序列
是位置1->位置8,2->4,2->7,3->5,4->6,5->7。

 

输入格式:
第一行:T,表示数据组数
对于每组数据:
第一行:2个数,K,N
第二行:N个数,表示这个序列

 

输出格式:
共T行,每行一个数表示答案

 

样例输入:
2
7 3
1 2 3
4 8
2 1 2 1 1 2 1 2
 

样例输出:
0
6
 

数据范围:
30%数据满足:1<=T<=10,1<=N,K<=1000

100%数据满足:1<=T<=20,1<=N<=50000,1<=K<=1000000,序列的每个数<=1000000000

 

时间限制:
1S

 

空间限制:
256M
做法:

s [ i ] = ( a [ 1 ] + . . a [ i ] ) m o d k s[i]=(a[1]+..a[i])mod k s[i]=(a[1]+..a[i])modk
如果对于i,j,满足s[i]=s[j],那么子序列i+1…j是合法的。
从左往右求解即可。

附:AC代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
int t,n,ans,a[50005],sum[50005],k,cnt[1000005];
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>t;
	while(t--) {
		cin>>k>>n;
		ans=0;
		memset(sum,0,sizeof(sum));
		memset(cnt,0,sizeof(cnt));
		cnt[0]=1;
		for(int i=1; i<=n; i++) {
			cin>>a[i];
			sum[i]=sum[i-1]+a[i];
			cnt[sum[i]%k]++;
			ans+=(cnt[sum[i]%k]-1);
		}
		cout<<ans<<endl;
	}
	return 0;
}

T2:

题面:

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

做法:

dfs

附:AC代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int inf=1e17;
const double eps=1e-6;
typedef unsigned long long ull;
typedef pair<ull,ull> pii;
int n;
int pa[200005];
vector<int> e[200005];
int l[200005];
int r[200005];
int ans;
int dfs(int u){
    bool flag=1;
    int sum=0;
    for(int &v:e[u]){
        if(v==pa[u]) continue;
        flag=0;
        sum+=dfs(v);
    }
    int flow=min(sum,r[u]);
    if(flag){
        ans++;
        return r[u];
    }
    if(flow<l[u]) ans++,flow=r[u];
    return flow;
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(NULL),cout.tie(NULL);
    cin>>n;
    for(int i=2;i<=n;i++){
        cin>>pa[i];
        e[i].push_back(pa[i]);
        e[pa[i]].push_back(i);
    }
    for(int i=1;i<=n;i++)
        cin>>l[i]>>r[i];
    dfs(1);
    cout<<ans;
    return 0;
}

T3:

题面:

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

做法:

在这里插入图片描述

附:AC代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5e3 + 5;
int n, m, C;
int v[N], w[N], c[N], lim[N];
ll f[N][N], dp[N][N];
int pre[N][N];
int main(void) {
	scanf("%d %d %d", &n, &m, &C);
	for (int i = 1; i <= n; ++i) {
		scanf("%d %d %d", &v[i], &w[i], &c[i]);
		pre[c[i]][++pre[c[i]][0]] = i;
	}
	for (int i = 1; i <= C; ++i) {
		scanf("%d", &lim[i]);
		lim[i] = min(lim[i], m);
	}
	for (int i = 1; i <= C; ++i) {
		f[i][0] = 0;
		for (int j = 1; j <= pre[i][0]; ++j) {
			int k = pre[i][j];
			for (int l = lim[i]; l >= w[k]; --l) {
				f[i][l] = max(f[i][l], f[i][l - w[k]] + v[k]);
			}
		}
	}
	for (int i = 1; i <= C; ++i) {
		for (int j = 0; j <= m; ++j) {
			dp[i][j] = dp[i - 1][j];
		}
		for (int j = 0; j <= lim[i]; ++j) {
			for (int k = j; k <= m; ++k) {
				dp[i][k] = max(dp[i][k], dp[i - 1][k - j] + f[i][j]);
			}
		}
	}
	printf("%lld", dp[C][m]);
    return 0;
}

T4:

题面:

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

做法:

在这里插入图片描述

附:AC代码
#include<bits/stdc++.h>
using namespace std;
const int mod=19260817;
int a[10000010],n,inv[10000010],ans;
int main(){
	cin>>n;
	for(int i=1;i<=n;++i) cin>>a[i];
	sort(a+1,a+1+n);
	inv[1]=1;
	for(int i=2;i<=a[n];++i){
		int j=mod/i+1;
		inv[i]=1ll*j*inv[i*j-mod]%mod;
	}
	for(int i=n;i;i--)
		for(int j=a[i];j>a[i-1];j--) 
			ans=(ans+1ll*a[i]*inv[a[n]-j+1])%mod;
	cout<<ans;
	return 0;
}

三、赛后总结

我就是24k纯菜

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值