20230801模拟赛

20230801模拟赛

T1三值的排序

题意

给定 \(n\) 个数,每个数为 \(1,2,3\),给这 \(n\) 个数排序。排序方法为每次交换两个数求,最小交换次数。

题解

显然可以求出三个数每个数的区间,然后考虑贪心交换次序,先把 \(1\) 区间里的 \(2\)\(2\) 区间里的 \(1\) 交换,以此类推。

T2日记

题意

给定 \(N,k\),询问不超过的数中能够表示成连续的个质数之和的最大的数是多少?

题解

显然要选连续的,而答案存在随着数值增大可行性递减,所以前缀和加二分。

T3分蛋糕

题意

给定一个长度为 \(n\) 的环,每一部分有一个权值 \(a_i\),且权值互不相同,现在小 \(Y\) 和小 \(Z\),准备拿走这些权值,首先小 \(Y\) 任意拿走一个,然后从小 \(Z\) 开始,两人交替拿走剩下的值,并且被拿走的值要满足旁边一个或两个值已经被拿走。

问如果小 \(Z\) 每次拿能拿的最大权值的情况下,小 \(Y\) 能拿到权值的最大和为多少。

题解

考虑 \(dp\) 设状态为 \(f_{l,r}\) 为剩余的权值的区间为 \([l,l+1,l+2,\dots,r-1,r]\)(可能会跨过 \(n\),如 \([l,l+1,\dots,n,1,\dots,r]\))。

然后每次 \(l-1,r+1\) 进行 \(dp\)\(l\)\(r\) 的长度为阶段,即拿掉的个数。枚举长度和 \(l\)\(r\) 可以直接求出来,然后 \(dp\) 式子简单。

T4都市

\(N\) 个数,但不给你,而是给了你 \(N\times (N-1)/2\) 个数,代表它们两两的和。

题解

题外话:考试时快想出来了,\(sb\) 了,大小比较比较个没完。

\(n(n-1)/2=m\)

首先先把 \(m\) 个数排序。

显然最小的数字一定是 \(a_1+a_2\),次小的数字一定是 \(a_1+a_3\)

然后枚举 \(a_2+a_3\),这样就可以求出来 \(a_1,a_2,a_3\)

然后最小的是 \(a_1+a_4\),求出来 \(a_4\),删去 \(a_2+a_4,a_3+a_4\),然后以此类推。

删数可以用 \(multiset\)

T5街灯

题意

给定 \(n\) 个数 \(a_i(1\leq a_i\leq 10^4)\),有 \(m\) 次询问,每次询问,给定 \(l,r,q,v\),问 \(\sum_{i=l}^r [a_i \equiv v\pmod p]\)

\(1\leq n,m \leq 10^5,1\leq q \leq 10^9\)

题解

震惊我了,根号分治好题呀!

先考虑 \(q\) 全部相同怎么做?将所有数字对 \(p\) 取模。问题就变成了:询问区间内等于某个数的数字有多少个?

对于每个值都开一个 vector,将模 \(p\) 值为 \(x\) 的数字的下标都存在一起。 每次询问直接在对的vector 里面二分第一个 \(\leq l\) 的位置和第一个 \(>r\) 的位置。时间复杂度为 \(O(n+mlogn)\)

因为 \(1\leq a_i\leq 10^4\),所以分块/根号分治。

  1. \(p>100\),则 \(10^4\) 以内模 \(p\) 等于 \(v\) 的只有至多 \(100\) 个数(\(v,v+q,v+2q,v+3q,\dots\)),相当于每次询问都可以按照 \(q\) 相同的做法来做。

  2. \(p\leq 100\) 时,每个数字 \(\bmod p\) 后最多也有 \(100\) 个数也可以用上面的做法求解。

代码参考:

n=read();m=read();
for(int i=1;i<=n;i++){
    a[i]=read();
    vt[a[i]].push_back(i);
}
while(m--){
    int l=read(),r=read(),q=read(),x=read(),sum=0;
    for(int i=x;i<=10000;i+=q)sum+=upper_bound(vt[i].begin(),vt[i].end(),r)-lower_bound(vt[i].begin(),vt[i].end(),l);
    printf("%lld\n",sum);
}
posted @ 2023-08-29 20:46  sunzz3183  阅读(11)  评论(0编辑  收藏  举报
Live2D