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 补题报告2023年7月21日−2024年7月21日by 邓时飏
一、做题情况
-
第一题比赛 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纯菜