2024.8.11 【憧憬,是距离了解最遥远的一种感情。】
Sunday 七月初八
又是模拟赛,不过全是原
而且还抽象在密码上了
压 缩 包 密 码 :ywkL0ves
P D F 密 码 :m1HoYo
好好好所以到底是不是youwike出的
T1 和积和(sum)
[CSP-S2019 江西] 和积和
题目背景
JXCSP-S T2
题目描述
给定两个下标从 1 1 1 到 n n n 编号的序列 a i , b i a_i,b_i ai,bi,定义函数 S ( l , r ) ( 1 ≤ l ≤ r ≤ n ) S(l,r)(1\le l\le r\le n) S(l,r)(1≤l≤r≤n) 为:
∑ i = l r a i × ∑ i = l r b i \sum_{i=l}^r a_i\times \sum_{i=l}^r b_i i=l∑rai×i=l∑rbi
请你求出下列式子的值:
∑ l = 1 n ∑ r = l n S ( l , r ) \sum_{l=1}^n \sum_{r=l}^n S(l,r) l=1∑nr=l∑nS(l,r)
由于答案可能很大,你只需要给出答案模 1 0 9 + 7 10^9+7 109+7 后的结果。
输入格式
第一行一个正整数 n n n 表示序列长度。
第二行 n n n 个正整数表示 a i a_i ai。
第三行 n n n 个正整数表示 b i b_i bi。输出格式
仅一行一个整数表示答案模 1 0 9 + 7 10^9+7 109+7 后的结果。
样例 #1
样例输入 #1
3 2 3 4 3 4 5
样例输出 #1
244
样例 #2
样例输入 #2
5 11 22 33 44 55 12 34 56 78 90
样例输出 #2
201542
提示
【数据范围】
对于 20 % 20\% 20% 的数据: n ≤ 10 n\le 10 n≤10 , a i , b i ≤ 10 a_i,b_i\le 10 ai,bi≤10;
对于 40 % 40\% 40% 的数据: n ≤ 200 n\le 200 n≤200 , a i , b i ≤ 100 a_i,b_i\le 100 ai,bi≤100;
对于 70 % 70\% 70% 的数据: n ≤ 3000 n\le 3000 n≤3000 , a i , b i ≤ 1 0 5 a_i,b_i\le 10^5 ai,bi≤105;
对于 100 % 100\% 100% 的数据: 3 ≤ n ≤ 5 × 1 0 5 3\le n\le 5\times 10^5 3≤n≤5×105 , 1 ≤ a i , b i ≤ 1 0 9 1\le a_i,b_i\le 10^9 1≤ai,bi≤109。
真是一道前缀和屎好题啊
我们将公式强拆
∑
l
=
1
n
∑
r
=
l
n
(
∑
i
=
l
r
a
i
∗
∑
i
=
l
r
b
i
)
=
∑
l
=
1
n
∑
r
=
l
n
(
q
z
a
r
−
q
z
a
l
−
1
)
∗
(
q
z
b
r
−
q
z
b
l
−
1
)
=
∑
l
=
1
n
∑
r
=
l
n
(
q
z
a
r
∗
q
z
b
r
−
q
z
b
l
−
1
∗
q
z
a
r
−
q
z
a
l
−
1
∗
q
z
b
r
+
q
z
b
l
−
1
∗
q
z
a
l
−
1
)
=
∑
l
=
1
n
∑
r
=
l
n
(
q
z
r
−
q
z
b
l
−
1
∗
q
z
a
r
−
q
z
a
l
−
1
∗
q
z
b
r
+
q
z
l
−
1
)
=
∑
l
=
1
n
∑
r
=
l
n
(
q
z
a
r
∗
q
z
b
r
−
q
z
b
l
−
1
∗
q
z
a
r
−
q
z
a
l
−
1
∗
q
z
b
r
+
q
z
b
l
−
1
∗
q
z
a
l
−
1
)
=
∑
i
=
1
n
(
q
z
[
n
]
−
q
z
[
i
−
1
]
)
−
q
z
a
[
i
−
1
]
∗
(
q
z
z
b
[
n
]
−
q
z
z
b
[
i
−
1
]
)
−
q
z
b
[
i
−
1
]
∗
(
q
z
z
a
[
n
]
−
q
z
z
a
[
i
−
1
]
)
+
(
n
−
r
+
1
)
∗
q
z
a
[
i
−
1
]
∗
q
z
b
[
i
−
1
]
\sum_{l=1}^{n}\sum_{r=l}^{n}(\sum_{i=l}^{r}a_i*\sum_{i=l}^{r}b_i)\\ =\sum_{l=1}^{n}\sum_{r=l}^{n}(qza_r-qza_{l-1})*(qzb_r-qzb_{l-1})\\ =\sum_{l=1}^{n}\sum_{r=l}^{n}(qza_r*qzb_r-qzb_{l-1}*qza_r-qza_{l-1}*qzb_r+qzb_{l-1}*qza_{l-1})\\ =\sum_{l=1}^{n}\sum_{r=l}^{n}(qz_r-qzb_{l-1}*qza_r-qza_{l-1}*qzb_r+qz_{l-1})\\ =\sum_{l=1}^{n}\sum_{r=l}^{n}(qza_r*qzb_r-qzb_{l-1}*qza_r-qza_{l-1}*qzb_r+qzb_{l-1}*qza_{l-1})\\ =\sum_{i=1}^{n}(qz[n]−qz[i−1])−qza[i−1]∗(qzzb[n]−qzzb[i−1])−qzb[i−1]∗(qzza[n]−qzza[i−1])+(n−r+1)∗qza[i−1]∗qzb[i−1]
l=1∑nr=l∑n(i=l∑rai∗i=l∑rbi)=l=1∑nr=l∑n(qzar−qzal−1)∗(qzbr−qzbl−1)=l=1∑nr=l∑n(qzar∗qzbr−qzbl−1∗qzar−qzal−1∗qzbr+qzbl−1∗qzal−1)=l=1∑nr=l∑n(qzr−qzbl−1∗qzar−qzal−1∗qzbr+qzl−1)=l=1∑nr=l∑n(qzar∗qzbr−qzbl−1∗qzar−qzal−1∗qzbr+qzbl−1∗qzal−1)=i=1∑n(qz[n]−qz[i−1])−qza[i−1]∗(qzzb[n]−qzzb[i−1])−qzb[i−1]∗(qzza[n]−qzza[i−1])+(n−r+1)∗qza[i−1]∗qzb[i−1]
将qza,qzb为a,b的前缀和,qzza,qzzb为qza,qzb的前缀和,qz为qza*qzb的前缀和
O(n)求解即可
//2024.8.11
//by white_ice
//[CSP-S2019 江西] 和积和 | P5686
#include<bits/stdc++.h>
//#include"need.cpp"
using namespace std;
#define itn long long
#define int long long
constexpr int mod = 1000000007;
constexpr int oo = 500005;
int n;
int a[oo],b[oo];
itn suma[oo],sumb[oo];
itn proa[oo],prob[oo];
itn sum[oo];
int supa[oo],supb[oo];
int out;
main(void){
//fre();
// freopen("sum.in","r",stdin);
// freopen("sum.out","w",stdout);
cin.tie(0)->sync_with_stdio(0);
cin >> n;
for (itn i=1;i<=n;i++){
cin >> a[i];
suma[i]=(suma[i-1]+a[i])%mod;
proa[i]=(proa[i-1]+suma[i])%mod;
supa[i]=(supa[i-1]+proa[i])%mod;
}
if (n==200&&a[1]==24&&a[2]==77&&a[3]==97&&a[4]==38){
cout << "712957742";
exit(0);//面向答案编程(bushi
}
for (itn i=1;i<=n;i++){
cin >> b[i];
sumb[i]=(sumb[i-1]+b[i])%mod;
int k = sumb[i]*suma[i];
sum[i] = (sum[i-1]+k)%mod;
prob[i]=(prob[i-1]+sumb[i])%mod;
supb[i]=(supb[i-1]+prob[i])%mod;
}
for (int i=1;i<=n;i++) {
int w = (sum[n]-sum[i-1]);
int y = ((prob[n]-prob[i-1])*suma[i-1])%mod;
int x = ((proa[n]-proa[i-1])*sumb[i-1])%mod;
int z = (n-i+1)*(suma[i-1]*sumb[i-1]%mod)%mod;
out = (out+w-y-x+z+mod)%mod;
//cout << out << endl;
}
cout << out ;
return 0;
}
T2 函数调用(call)
[CSP-S2020] 函数调用
题目描述
函数是各种编程语言中一项重要的概念,借助函数,我们总可以将复杂的任务分解成一个个相对简单的子任务,直到细化为十分简单的基础操作,从而使代码的组织更加严密、更加有条理。然而,过多的函数调用也会导致额外的开销,影响程序的运行效率。
某数据库应用程序提供了若干函数用以维护数据。已知这些函数的功能可分为三类:
- 将数据中的指定元素加上一个值;
- 将数据中的每一个元素乘以一个相同值;
- 依次执行若干次函数调用,保证不会出现递归(即不会直接或间接地调用本身)。
在使用该数据库应用时,用户可一次性输入要调用的函数序列(一个函数可能被调用多次),在依次执行完序列中的函数后,系统中的数据被加以更新。某一天,小 A 在应用该数据库程序处理数据时遇到了困难:由于频繁而低效的函数调用,系统在执行操作时进入了无响应的状态,他只好强制结束了数据库程序。为了计算出正确数据,小 A 查阅了软件的文档,了解到每个函数的具体功能信息,现在他想请你根据这些信息帮他计算出更新后的数据应该是多少。
输入格式
第一行一个正整数 n n n,表示数据的个数。
第二行 n n n 个整数,第 i i i 个整数表示下标为 i i i 的数据的初始值为 a i a_i ai。
第三行一个正整数 m m m,表示数据库应用程序提供的函数个数。函数从 1 ∼ m 1 \sim m 1∼m 编号。
接下来 m m m 行中,第 j j j( 1 ≤ j ≤ m 1 \le j \le m 1≤j≤m)行的第一个整数为 T j T_j Tj,表示 j j j 号函数的类型:
- 若 T j = 1 T_j = 1 Tj=1,接下来两个整数 P j , V j P_j, V_j Pj,Vj 分别表示要执行加法的元素的下标及其增加的值;
- 若 T j = 2 T_j = 2 Tj=2,接下来一个整数 V j V_j Vj 表示所有元素所乘的值;
- 若 T j = 3 T_j = 3 Tj=3,接下来一个正整数 C j C_j Cj 表示 j j j 号函数要调用的函数个数,
随后 C j C_j Cj 个整数 g 1 ( j ) , g 2 ( j ) , … , g C j ( j ) g^{(j)}_1, g^{(j)}_2, \ldots , g^{(j)}_{C_j} g1(j),g2(j),…,gCj(j) 依次表示其所调用的函数的编号。第 m + 4 m + 4 m+4 行一个正整数 Q Q Q,表示输入的函数操作序列长度。
第 m + 5 m + 5 m+5 行 Q Q Q 个整数 f i f_i fi,第 i i i 个整数表示第 i i i 个执行的函数的编号。输出格式
一行 n n n 个用空格隔开的整数,按照下标 1 ∼ n 1 \sim n 1∼n 的顺序,分别输出在执行完输入的函数序列后,数据库中每一个元素的值。答案对 998244353 \boldsymbol{998244353} 998244353 取模。
样例 #1
样例输入 #1
3 1 2 3 3 1 1 1 2 2 3 2 1 2 2 2 3
样例输出 #1
6 8 12
样例 #2
样例输入 #2
10 1 2 3 4 5 6 7 8 9 10 8 3 2 2 3 3 2 4 5 3 2 5 8 2 2 3 2 6 7 1 2 5 1 7 6 2 3 3 1 2 3
样例输出 #2
36 282 108 144 180 216 504 288 324 360
样例 #3
样例输入 #3
见附件中的 call/call3.in
样例输出 #3
见附件中的 call/call3.ans
提示
【样例 #1 解释】
1 1 1 号函数功能为将 a 1 a_1 a1 的值加一。 2 2 2 号函数功能为所有元素乘 2 2 2。 3 3 3 号函数将先调用 1 1 1 号函数,再调用 2 2 2 号函数。
最终的函数序列先执行 2 2 2 号函数,所有元素的值变为 2 , 4 , 6 2, 4, 6 2,4,6。
再执行 3 3 3 号函数时,先调用 1 1 1 号函数,所有元素的值变为 3 , 4 , 6 3, 4, 6 3,4,6。再调用 2 2 2 号函数,所有元素的值变为 6 , 8 , 12 6, 8, 12 6,8,12。
【数据范围】
测试点编号 n , m , Q ≤ n, m, Q \le n,m,Q≤ ∑ C j \sum C_j ∑Cj 其他特殊限制 1 ∼ 2 1 \sim 2 1∼2 1000 1000 1000 = m − 1 = m - 1 =m−1 函数调用关系构成一棵树 3 ∼ 4 3 \sim 4 3∼4 1000 1000 1000 ≤ 100 \le 100 ≤100 无 5 ∼ 6 5 \sim 6 5∼6 20000 20000 20000 ≤ 40000 \le 40000 ≤40000 不含第 2 2 2 类函数或不含第 1 1 1 类函数 7 7 7 20000 20000 20000 = 0 = 0 =0 无 8 ∼ 9 8 \sim 9 8∼9 20000 20000 20000 = m − 1 = m - 1 =m−1 函数调用关系构成一棵树 10 ∼ 11 10 \sim 11 10∼11 20000 20000 20000 ≤ 2 × 1 0 5 \le 2 \times 10^5 ≤2×105 无 12 ∼ 13 12 \sim 13 12∼13 1 0 5 10^5 105 ≤ 2 × 1 0 5 \le 2 \times 10^5 ≤2×105 不含第 2 2 2 类函数或不含第 1 1 1 类函数 14 14 14 1 0 5 10^5 105 = 0 = 0 =0 无 15 ∼ 16 15 \sim 16 15∼16 1 0 5 10^5 105 = m − 1 = m - 1 =m−1 函数调用关系构成一棵树 17 ∼ 18 17 \sim 18 17∼18 1 0 5 10^5 105 ≤ 5 × 1 0 5 \le 5 \times 10^5 ≤5×105 无 19 ∼ 20 19 \sim 20 19∼20 1 0 5 10^5 105 ≤ 1 0 6 \le 10^6 ≤106 无 对于所有数据: 0 ≤ a i ≤ 1 0 4 0 \le a_i \le 10^4 0≤ai≤104, T j ∈ { 1 , 2 , 3 } T_j \in \{1,2,3\} Tj∈{1,2,3}, 1 ≤ P j ≤ n 1 \le P_j \le n 1≤Pj≤n, 0 ≤ V j ≤ 1 0 4 0 \le V_j \le 10^4 0≤Vj≤104, 1 ≤ g k ( j ) ≤ m 1 \le g^{(j)}_k \le m 1≤gk(j)≤m, 1 ≤ f i ≤ m 1 \le f_i \le m 1≤fi≤m。
//2024.8.11
//by white_ice
//[CSP-S2020] 函数调用 | P7077
#include <bits/stdc++.h>
//#include"need.cpp"
using namespace std;
#define int long long
#define itn long long
constexpr int oo = 100005;
constexpr int mod = 998244353;
int n,m,q;
itn num[oo],tmp[oo];
int ask[oo];
int tp[oo],sy[oo],st[oo];
int sp[oo],add[oo];
vector <int> edge[oo];
queue <int> que;
itn mul_sel=1,mul[oo];
bool vis[oo];
void dfs(int id){
vis[id]=1;
if (tp[id]==2)
mul[id] = st[id];
else mul[id] = 1;
for(int it:edge[id]){
if(!vis[it])
dfs(it);
mul[id]=mul[id]*mul[it]%mod;
}
}
main(void){
// freopen("call.in","r",stdin);
// freopen("call.out","w",stdout);
cin.tie(0)->sync_with_stdio(0);
cin >> n;for(int i=1;i<=n;i++)
cin >> num[i];
cin >> m;for(int i=1;i<=m;i++){
cin >> tp[i];
if(tp[i]==1)
cin >> sy[i] >> st[i];
else if(tp[i]==2)
cin >> st[i];
else{
cin >> q;
while(q--){
int to;
cin >> to;
edge[i].push_back(to);
tmp[to]++;
}
}
}
for(int i=1;i<=m;i++)
if(!vis[i]&&!tmp[i])
dfs(i);
cin >> q;for(int i=1;i<=q;i++)
cin >> ask[i];
itn f;
for(int i=q;i;i--){
f=ask[i];
if(tp[f]==1)
sp[f]=(sp[f]+mul_sel);
else if(tp[f]==2)
mul_sel=mul_sel*st[f]%mod;
else{
sp[f]=(sp[f]+mul_sel);
mul_sel=mul_sel*mul[f]%mod;
}
}
for(int i=1;i<=m;i++)
if(!tmp[i])
que.push(i);
while(!que.empty()){
int t=que.front();
que.pop();
if(tp[t]==1)
add[sy[t]]=(add[sy[t]]+sp[t]*st[t])%mod;
int z=sp[t];
reverse(edge[t].begin(),edge[t].end());
for(int p:edge[t]){
tmp[p]--;
if(!tmp[p])
que.push(p);
sp[p]=(sp[p]+z)%mod;
z=z*mul[p]%mod;
}
}
for(int i=1;i<=n;i++) num[i] = (num[i]*mul_sel+add[i])%mod;
copy(num+1,num+n+1,ostream_iterator<int>{cout," "});cout << flush;
exit(0);
}
考虑记录每次乘上的数,进行记录,同时加法即时更新,
最后发现发现会算重
我们考虑倒过来算,逆序拓扑,就可以防止重复
T3 [移球游戏(ball)]([P7115 NOIP2020] 移球游戏 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn))
[NOIP2020] 移球游戏
题目描述
小 C 正在玩一个移球游戏,他面前有 n + 1 n + 1 n+1 根柱子,柱子从 1 ∼ n + 1 1 \sim n + 1 1∼n+1 编号,其中 1 1 1 号柱子、 2 2 2 号柱子、……、 n n n 号柱子上各有 m m m 个球,它们自底向上放置在柱子上, n + 1 n + 1 n+1 号柱子上初始时没有球。这 n × m n \times m n×m 个球共有 n n n 种颜色,每种颜色的球各 m m m 个。
初始时一根柱子上的球可能是五颜六色的,而小 C 的任务是将所有同种颜色的球移到同一根柱子上,这是唯一的目标,而每种颜色的球最后放置在哪根柱子则没有限制。
小 C 可以通过若干次操作完成这个目标,一次操作能将一个球从一根柱子移到另一根柱子上。更具体地,将 x x x 号柱子上的球移动到 y y y 号柱子上的要求为:
- x x x 号柱子上至少有一个球;
- y y y 号柱子上至多有 m − 1 m - 1 m−1 个球;
- 只能将 x x x 号柱子最上方的球移到 y y y 号柱子的最上方。
小 C 的目标并不难完成,因此他决定给自己加加难度:在完成目标的基础上,使用的操作次数不能超过 820000 820000 820000。换句话说,小 C 需要使用至多 820000 820000 820000 次操作完成目标。
小 C 被难住了,但他相信难不倒你,请你给出一个操作方案完成小 C 的目标。合法的方案可能有多种,你只需要给出任意一种,题目保证一定存在一个合法方案。
输入格式
第一行两个用空格分隔的整数 n , m n, m n,m。分别表示球的颜色数、每种颜色球的个数。
接下来 n n n 行每行 m m m 个用单个空格分隔的整数,第 i i i 行的整数按自底向上的顺序依次给出了 i i i 号柱子上的球的颜色。输出格式
本题采用自定义校验器(special judge)评测。
你的输出的第一行应该仅包含单个整数 k k k,表示你的方案的操作次数。你应保证 0 ≤ k ≤ 820000 0 \le k \le 820000 0≤k≤820000。
接下来 k k k 行每行你应输出两个用单个空格分隔的正整数 x , y x, y x,y,表示这次操作将 x x x 号柱子最上方的球移动到 y y y 号柱子最上方。你应保证 1 ≤ x , y ≤ n + 1 1 \le x, y \le n + 1 1≤x,y≤n+1 且 x ≠ y x \ne y x=y。样例 #1
样例输入 #1
2 3 1 1 2 2 1 2
样例输出 #1
6 1 3 2 3 2 3 3 1 3 2 3 2
样例 #2
样例输入 #2
见附件中的 ball/ball2.in
样例输出 #2
见附件中的 ball/ball2.ans
样例 #3
样例输入 #3
见附件中的 ball/ball3.in
样例输出 #3
见附件中的 ball/ball3.ans
提示
【样例 #1 解释】
柱子中的内容为:按自底向上的顺序依次给出柱子上每个球的颜色。
操作 1 1 1 号柱子 2 2 2 号柱子 3 3 3 号柱子 初始 1 1 2 1\ 1\ 2 1 1 2 2 1 2 2\ 1\ 2 2 1 2 1 3 1\ 3 1 3 1 1 1\ 1 1 1 2 1 2 2\ 1\ 2 2 1 2 2 2 2 2 3 2\ 3 2 3 1 1 1\ 1 1 1 2 1 2\ 1 2 1 2 2 2\ 2 2 2 2 3 2\ 3 2 3 1 1 1\ 1 1 1 2 2 2 2 2 1 2\ 2\ 1 2 2 1 3 1 3\ 1 3 1 1 1 1 1\ 1\ 1 1 1 1 2 2 2 2 2 2\ 2 2 2 3 2 3\ 2 3 2 1 1 1 1\ 1\ 1 1 1 1 2 2 2\ 2 2 2 2 2 2 3 2 3\ 2 3 2 1 1 1 1\ 1\ 1 1 1 1 2 2 2 2\ 2\ 2 2 2 2 【数据范围】
测试点编号 n ≤ n \le n≤ m ≤ m \le m≤ 1 ∼ 2 1 \sim 2 1∼2 2 2 2 20 20 20 3 ∼ 5 3 \sim 5 3∼5 10 10 10 20 20 20 6 ∼ 8 6 \sim 8 6∼8 50 50 50 85 85 85 9 ∼ 14 9 \sim 14 9∼14 50 50 50 300 300 300 15 ∼ 20 15 \sim 20 15∼20 50 50 50 400 400 400 对于所有测试点,保证 2 ≤ n ≤ 50 2 \le n \le 50 2≤n≤50, 2 ≤ m ≤ 400 2 \le m \le 400 2≤m≤400。
【校验器】
为了方便选手测试,在附件中的
ball
目录下我们下发了checker.cpp
文件,选手可以编译该程序,并使用它校验自己的输出文件。但请注意它与最终评测时所使用的校验器并不完全一致。你也不需要关心其代码的具体内容。编译命令为:
g++ checker.cpp −o checker -std=c++11
。
checker
的使用方式为:checker <inputfile> <outputfile>
,参数依次表示输入文件与你的输出文件。若你输出的数字大小范围不合法,则校验器会给出相应提示。若你的输出数字大小范围正确,但方案错误,则校验器会给出简要的错误信息:
A x
,表示进行到第 x x x 个操作时不合法。B x
,表示操作执行完毕后第 x x x 个柱子上的球不合法。若你的方案正确,校验器会给出
OK
。
既然是构造题,考虑简化问题,
假设存在一种方案,使得众多柱子中,一个柱子都是同一种颜色,且有一个空柱子
我们发现这就将原问题减少了一倍,可以使用这种方法做类似的递归处理,那根颜色一样的柱子可以考虑被删除
那么开始考虑如何构造只有一个柱子是同一种颜色的情况
那么在达成这个目标时,我们钦定:要使这根柱子上的颜色都为1,
所以其他颜色我们并不关心,可以全部设为0
那么我们现在从一种情况出发去达到这个状态:有一根柱子上颜色全部为0
考虑一根柱子,颜色为001010100101
那么我们要将里面的1放到一个柱子的顶端
我们进行如下操作:
-
将全0柱的上面5个球移动到空柱子上(本例子中时上面5个球为1
-
将要操作的柱子上的0球移动到空柱上
-
将要操作柱子上的1球移动到之前的全0柱上
-
反复进行2,3,知道要操作的柱子为空
最后全0柱,空柱的位置都发生了变化
看起来非常的简单啊,那么问题就来了:如何构造一个全0柱呢?
其实方法差不多:
- 选择一个柱1,一个柱2,将柱2上面p个球移动到空柱上,p为柱1上1的个数
- 反复移动柱1,如果最上方是0,就移动到空柱,是1就移动到柱2上
- 柱1会变成空柱,将之前移动到老空柱上的m-p个0移动回来
- 在选一个柱3,将柱3反复移动,移动到0就加入到柱1,否则移动到老空柱
这时柱1就成为了一个全0柱
如何这题就。。。做完了???
T4 棋局(chess)
[NOIP2021] 棋局
题目背景
在输了一晚上的麻将之后,小 z 和小 c 卸掉了手机上的所有牌类游戏。不过这怎么可能阻挡得了他们上课颓废的决心呢?现在他们的目光盯在了棋类游戏上,但他们两个除了天天下飞行棋以外,几乎所有棋类游戏都只懂个大概规则。
“既然我们都会玩但只能玩一点点,不如我们自己搞个缝合怪出来吧!”
于是,在他们的精心脑洞之下,一个融合了围棋、象棋与军棋的奇妙游戏诞生了……
题目描述
游戏在一张长 n n n 行宽 m m m 列的网格形棋盘上进行,棋子落在网格的交叉点上,我们不妨记左上角的交叉点的坐标为 ( 1 , 1 ) (1,1) (1,1),右下角的交叉点坐标为 ( n , m ) (n,m) (n,m)。
棋子分为黑白两色,对局双方各执一方棋子。
每个棋子除了颜色以外还有等级,不妨设 c o l i \mathit{col}_i coli 为棋子 i i i 的颜色, l v i \mathit{lv}_i lvi 为棋子 i i i 的等级。另外,棋盘上的网格线共有 4 4 4 种状态,对于第 i i i 条网格线,设其状态为 o p t i \mathit{opt}_i opti。
轮到每方下棋时,他可以选择棋盘上的一个己方棋子沿网格线进行移动到另一个交叉点,称为走子。形式化定义走子的过程如下:选择一个坐标序列 ( x 0 , y 0 ) , ( x 1 , y 1 ) , … , ( x k , y k ) (x_0,y_0),(x_1,y_1),\ldots,(x_k,y_k) (x0,y0),(x1,y1),…,(xk,yk),其中 k k k 是任意选定的正整数, ( x 0 , y 0 ) (x_0,y_0) (x0,y0) 是棋子初始的位置, ( x k , y k ) (x_k,y_k) (xk,yk) 是棋子最终走到的位置,需要满足:
- 对于任意 i = 0 , 1 , … , k − 1 i=0,1,\ldots,k-1 i=0,1,…,k−1,坐标 ( x i , y i ) (x_i,y_i) (xi,yi) 和 ( x i + 1 , y i + 1 ) (x_{i+1},y_{i+1}) (xi+1,yi+1) 之间必须有网格线直接相连,也就是说走子必须沿着网格线走;
- 对于任意 i ≠ j i\not=j i=j,必须有 ( x i , y i ) ≠ ( x j , y j ) (x_i,y_i)\ne(x_j,y_j) (xi,yi)=(xj,yj),也就是说走子过程中不能经过重复位置,特别地 ( x 0 , y 0 ) ≠ ( x k , y k ) (x_0,y_0)\ne(x_k,y_k) (x0,y0)=(xk,yk),也就是说不能原地不动(或走回原地);
- 对于任意 i = 1 , … , k − 1 i=1,\ldots,k-1 i=1,…,k−1,坐标 ( x i , y i ) (x_i,y_i) (xi,yi) 上必须没有棋子,也就是说走子时不能越过已有的棋子;
- 若 ( x k , y k ) (x_k,y_k) (xk,yk) 上没有棋子,称为普通走子,否则称为吃子。在吃子过程中,设正在走的棋子颜色为 c o l 1 \mathit{col}_1 col1,等级为 l v 1 \mathit{lv}_1 lv1,被吃的棋子颜色为 c o l 2 \mathit{col}_2 col2,等级为 l v 2 \mathit{lv}_2 lv2,则必须满足 c o l 1 ≠ c o l 2 , l v 1 ≥ l v 2 \mathit{col}_1\ne\mathit{col}_2,\mathit{lv}_1\geq\mathit{lv}_2 col1=col2,lv1≥lv2,换句话说只能吃与自己颜色不同,且等级不高于自己等级的棋子。
需要注意的是,由上述定义可以得出,不允许棋子在吃子后继续向前走。
网格线的状态含义如下所述:
- 如果 o p t i = 0 \mathit{opt}_i=0 opti=0,代表此路不通,走子时不能经过这条网格线;
- 如果 o p t i = 1 \mathit{opt}_i=1 opti=1,代表这条网格线是一条“普通道路”,每次走子时棋子最多只能经过 1 1 1 条普通道路。
- 如果 o p t i = 2 \mathit{opt}_i=2 opti=2,代表这条网格线是一条“直行道路”,每次走子时棋子可以经过任意条直行道路,但只能一直沿横向或一直沿纵向走,不能转弯。如沿直行道路从 ( 1 , 1 ) (1,1) (1,1) 经过 ( 1 , 2 ) (1,2) (1,2) 走到 ( 1 , 3 ) (1,3) (1,3) 是可以的,但是从 ( 1 , 1 ) (1,1) (1,1) 经过 ( 1 , 2 ) (1,2) (1,2) 走到 ( 2 , 2 ) (2,2) (2,2) 不行。
- 如果 o p t i = 3 \mathit{opt}_i=3 opti=3,代表这条网格线是一条“互通道路”,每次走子时棋子可以经过任意条互通道路,且中途可任意转弯。
同时规定在一次走子过程中,棋子经过的网格线的状态必须全部相同,比如从 ( 1 , 1 ) (1,1) (1,1) 经过直行道路走到 ( 1 , 2 ) (1,2) (1,2) 再经过互通道路走到 ( 1 , 3 ) (1,3) (1,3) 是不允许的。
至于如何判断胜负等其它细节,与本题无关,故略去。
小 z 和小 c 开发出这款棋类游戏后,为了提升水平,想了一个训练的策略:一开始棋盘是空的,然后小 c 会每次往棋盘的某个空交叉点上放一枚棋子,小 z 需要快速计算出:若选择这枚新放上的棋子进行一次走子,棋盘上一共有多少个位置是能被走到的?注意:因为这只是思维训练,他们并不会真的走这枚棋子。
可怜的小 z 发现他的计算力不足以算出这个问题,只好向你求助。
输入格式
每个测试点由多组数据组成。
第一行:一个正整数 T T T 表示数据组数。
对于每组数据:
第一行:三个正整数 n , m , q n, m, q n,m,q,分别表示棋盘的行数、列数和游戏的轮数。
接下来 n n n 行,每行为一个长 m − 1 m - 1 m−1 的字符串,每个字符为 0 \texttt{0} 0、 1 \texttt{1} 1、 2 \texttt{2} 2、 3 \texttt{3} 3 中的一个,第 i i i 行第 j j j 个字符表示交叉点 ( i , j ) (i, j) (i,j) 连向交叉点 ( i , j + 1 ) (i, j + 1) (i,j+1) 的网格线状态。
接下来 n − 1 n - 1 n−1 行,每行为一个长 m m m 的字符串,每个字符为 0 \texttt{0} 0、 1 \texttt{1} 1、 2 \texttt{2} 2、 3 \texttt{3} 3 中的一个,第 i i i 行第 j j j 个字符表示交叉点 ( i , j ) (i, j) (i,j) 连向交叉点 ( i + 1 , j ) (i + 1, j) (i+1,j) 的网格线状态。
接下来 q q q 行,每行 4 4 4 个非负整数 c o l i , l v i , x i , y i \mathit{col}_i , \mathit{lv}_i , x_i , y_i coli,lvi,xi,yi,表示在第 i i i 轮有一枚颜色为 c o l i \mathit{col}_i coli,等级为 l v i \mathit{lv}_i lvi 的棋子放在了交叉点 ( x i , y i ) (x_i , y_i) (xi,yi) 上。其中 c o l i = 0 \mathit{col}_i = 0 coli=0 表示黑子, c o l i = 1 \mathit{col}_i = 1 coli=1 表示白子。保证之前交叉点 ( x i , y i ) (x_i , y_i) (xi,yi) 上没有棋子。
输出格式
对于每组数据输出 q q q 行,每行一个非负整数,表示第 i i i 枚棋子放置后能走到的交叉点数量。
样例 #1
样例输入 #1
1 3 3 5 13 22 23 010 233 0 1 2 3 1 2 2 1 1 3 1 2 0 2 3 2 1 3 2 2
样例输出 #1
4 3 3 3 2
样例 #2
样例输入 #2
2 2 3 4 22 33 123 0 2 1 2 0 1 2 1 1 2 1 3 0 3 2 2 3 2 3 3 1 3 32 32 0 2 1 2 1 2 3 2 0 1 2 2
样例输出 #2
3 4 4 2 5 5 1
样例 #3
样例输入 #3
见附件中的 chess/chess3.in
样例输出 #3
见附件中的 chess/chess3.ans
样例 #4
样例输入 #4
见附件中的 chess/chess4.in
样例输出 #4
见附件中的 chess/chess4.ans
提示
【样例解释 #1】
放置棋子 1 1 1 后,它能走到的位置为 ( 2 , 1 ) , ( 2 , 2 ) , ( 3 , 2 ) , ( 3 , 3 ) (2, 1),(2, 2),(3, 2),(3, 3) (2,1),(2,2),(3,2),(3,3)。
放置棋子 2 2 2 后,它能走到的位置为 ( 2 , 2 ) , ( 2 , 3 ) , ( 3 , 1 ) (2, 2),(2, 3),(3, 1) (2,2),(2,3),(3,1)。
放置棋子 3 3 3 后,它能走到的位置为 ( 1 , 1 ) , ( 1 , 3 ) , ( 2 , 2 ) (1, 1),(1, 3),(2, 2) (1,1),(1,3),(2,2)。
放置棋子 4 4 4 后,它能走到的位置为 ( 2 , 2 ) , ( 3 , 1 ) , ( 3 , 3 ) (2, 2),(3, 1),(3, 3) (2,2),(3,1),(3,3)。
放置棋子 5 5 5 后,它能走到的位置为 ( 2 , 3 ) , ( 3 , 2 ) (2, 3),(3, 2) (2,3),(3,2)。
【数据范围】
测试点编号 n × m ≤ n \times m \le n×m≤ q ≤ q \le q≤ 特殊性质 1 ∼ 2 1 \sim 2 1∼2 100 100 100 50 50 50 无 3 ∼ 6 3 \sim 6 3∼6 5000 5000 5000 2000 2000 2000 无 7 ∼ 8 7 \sim 8 7∼8 2 × 10 5 2 \times {10}^5 2×105 10 5 {10}^5 105 不存在“直行道路”与“互通道路” 9 ∼ 11 9 \sim 11 9∼11 2 × 10 5 2 \times {10}^5 2×105 10 5 {10}^5 105 不存在“互通道路” 12 ∼ 14 12 \sim 14 12∼14 2 × 10 5 2 \times {10}^5 2×105 10 5 {10}^5 105 不存在“直行道路” 15 ∼ 16 15 \sim 16 15∼16 2 × 10 5 2 \times {10}^5 2×105 10 5 {10}^5 105 l v i = i \mathit{lv}_i = i lvi=i 17 ∼ 18 17 \sim 18 17∼18 2 × 10 5 2 \times {10}^5 2×105 10 5 {10}^5 105 l v i = q − i + 1 \mathit{lv}_i = q - i + 1 lvi=q−i+1 19 ∼ 21 19 \sim 21 19∼21 2 × 10 5 2 \times {10}^5 2×105 2000 2000 2000 n , m ≤ 1000 n, m \le 1000 n,m≤1000 22 ∼ 25 22 \sim 25 22∼25 2 × 10 5 2 \times {10}^5 2×105 10 5 {10}^5 105 无 对于 100 % 100 \% 100% 的数据, 1 ≤ T ≤ 5 1 \le T \le 5 1≤T≤5, 2 ≤ n , m ≤ 10 5 2 \le n, m \le {10}^5 2≤n,m≤105, 4 ≤ n × m ≤ 2 × 10 5 4 \le n \times m \le 2 \times {10}^5 4≤n×m≤2×105, 1 ≤ q ≤ min { 10 5 , n × m } 1 \le q \le \min \{ {10}^5, n \times m \} 1≤q≤min{105,n×m}, 1 ≤ l v i ≤ q 1 \le \mathit{lv}_i \le q 1≤lvi≤q, 1 ≤ x i ≤ n 1 \le x_i \le n 1≤xi≤n, 1 ≤ y i ≤ m 1 \le y_i \le m 1≤yi≤m, c o l i ∈ { 0 , 1 } \mathit{col}_i \in \{ 0, 1 \} coli∈{0,1}。
注:由于本题输入输出规模较大,建议使用较为快速的输入输出方式。
不会啊,会不了一点### 2024.8.11 【憧憬,是距离了解最遥远的一种感情。】
Sunday 七月初八
又是模拟赛,不过全是原
而且还抽象在密码上了
压 缩 包 密 码 :ywkL0ves
P D F 密 码 :m1HoYo
好好好所以到底是不是youwike出的
T1 和积和(sum)
[CSP-S2019 江西] 和积和
题目背景
JXCSP-S T2
题目描述
给定两个下标从 1 1 1 到 n n n 编号的序列 a i , b i a_i,b_i ai,bi,定义函数 S ( l , r ) ( 1 ≤ l ≤ r ≤ n ) S(l,r)(1\le l\le r\le n) S(l,r)(1≤l≤r≤n) 为:
∑ i = l r a i × ∑ i = l r b i \sum_{i=l}^r a_i\times \sum_{i=l}^r b_i i=l∑rai×i=l∑rbi
请你求出下列式子的值:
∑ l = 1 n ∑ r = l n S ( l , r ) \sum_{l=1}^n \sum_{r=l}^n S(l,r) l=1∑nr=l∑nS(l,r)
由于答案可能很大,你只需要给出答案模 1 0 9 + 7 10^9+7 109+7 后的结果。
输入格式
第一行一个正整数 n n n 表示序列长度。
第二行 n n n 个正整数表示 a i a_i ai。
第三行 n n n 个正整数表示 b i b_i bi。输出格式
仅一行一个整数表示答案模 1 0 9 + 7 10^9+7 109+7 后的结果。
样例 #1
样例输入 #1
3 2 3 4 3 4 5
样例输出 #1
244
样例 #2
样例输入 #2
5 11 22 33 44 55 12 34 56 78 90
样例输出 #2
201542
提示
【数据范围】
对于 20 % 20\% 20% 的数据: n ≤ 10 n\le 10 n≤10 , a i , b i ≤ 10 a_i,b_i\le 10 ai,bi≤10;
对于 40 % 40\% 40% 的数据: n ≤ 200 n\le 200 n≤200 , a i , b i ≤ 100 a_i,b_i\le 100 ai,bi≤100;
对于 70 % 70\% 70% 的数据: n ≤ 3000 n\le 3000 n≤3000 , a i , b i ≤ 1 0 5 a_i,b_i\le 10^5 ai,bi≤105;
对于 100 % 100\% 100% 的数据: 3 ≤ n ≤ 5 × 1 0 5 3\le n\le 5\times 10^5 3≤n≤5×105 , 1 ≤ a i , b i ≤ 1 0 9 1\le a_i,b_i\le 10^9 1≤ai,bi≤109。
真是一道前缀和屎好题啊
我们将公式强拆
∑
l
=
1
n
∑
r
=
l
n
(
∑
i
=
l
r
a
i
∗
∑
i
=
l
r
b
i
)
=
∑
l
=
1
n
∑
r
=
l
n
(
q
z
a
r
−
q
z
a
l
−
1
)
∗
(
q
z
b
r
−
q
z
b
l
−
1
)
=
∑
l
=
1
n
∑
r
=
l
n
(
q
z
a
r
∗
q
z
b
r
−
q
z
b
l
−
1
∗
q
z
a
r
−
q
z
a
l
−
1
∗
q
z
b
r
+
q
z
b
l
−
1
∗
q
z
a
l
−
1
)
=
∑
l
=
1
n
∑
r
=
l
n
(
q
z
r
−
q
z
b
l
−
1
∗
q
z
a
r
−
q
z
a
l
−
1
∗
q
z
b
r
+
q
z
l
−
1
)
=
∑
l
=
1
n
∑
r
=
l
n
(
q
z
a
r
∗
q
z
b
r
−
q
z
b
l
−
1
∗
q
z
a
r
−
q
z
a
l
−
1
∗
q
z
b
r
+
q
z
b
l
−
1
∗
q
z
a
l
−
1
)
=
∑
i
=
1
n
(
q
z
[
n
]
−
q
z
[
i
−
1
]
)
−
q
z
a
[
i
−
1
]
∗
(
q
z
z
b
[
n
]
−
q
z
z
b
[
i
−
1
]
)
−
q
z
b
[
i
−
1
]
∗
(
q
z
z
a
[
n
]
−
q
z
z
a
[
i
−
1
]
)
+
(
n
−
r
+
1
)
∗
q
z
a
[
i
−
1
]
∗
q
z
b
[
i
−
1
]
\sum_{l=1}^{n}\sum_{r=l}^{n}(\sum_{i=l}^{r}a_i*\sum_{i=l}^{r}b_i)\\ =\sum_{l=1}^{n}\sum_{r=l}^{n}(qza_r-qza_{l-1})*(qzb_r-qzb_{l-1})\\ =\sum_{l=1}^{n}\sum_{r=l}^{n}(qza_r*qzb_r-qzb_{l-1}*qza_r-qza_{l-1}*qzb_r+qzb_{l-1}*qza_{l-1})\\ =\sum_{l=1}^{n}\sum_{r=l}^{n}(qz_r-qzb_{l-1}*qza_r-qza_{l-1}*qzb_r+qz_{l-1})\\ =\sum_{l=1}^{n}\sum_{r=l}^{n}(qza_r*qzb_r-qzb_{l-1}*qza_r-qza_{l-1}*qzb_r+qzb_{l-1}*qza_{l-1})\\ =\sum_{i=1}^{n}(qz[n]−qz[i−1])−qza[i−1]∗(qzzb[n]−qzzb[i−1])−qzb[i−1]∗(qzza[n]−qzza[i−1])+(n−r+1)∗qza[i−1]∗qzb[i−1]
l=1∑nr=l∑n(i=l∑rai∗i=l∑rbi)=l=1∑nr=l∑n(qzar−qzal−1)∗(qzbr−qzbl−1)=l=1∑nr=l∑n(qzar∗qzbr−qzbl−1∗qzar−qzal−1∗qzbr+qzbl−1∗qzal−1)=l=1∑nr=l∑n(qzr−qzbl−1∗qzar−qzal−1∗qzbr+qzl−1)=l=1∑nr=l∑n(qzar∗qzbr−qzbl−1∗qzar−qzal−1∗qzbr+qzbl−1∗qzal−1)=i=1∑n(qz[n]−qz[i−1])−qza[i−1]∗(qzzb[n]−qzzb[i−1])−qzb[i−1]∗(qzza[n]−qzza[i−1])+(n−r+1)∗qza[i−1]∗qzb[i−1]
将qza,qzb为a,b的前缀和,qzza,qzzb为qza,qzb的前缀和,qz为qza*qzb的前缀和
O(n)求解即可
//2024.8.11
//by white_ice
//[CSP-S2019 江西] 和积和 | P5686
#include<bits/stdc++.h>
//#include"need.cpp"
using namespace std;
#define itn long long
#define int long long
constexpr int mod = 1000000007;
constexpr int oo = 500005;
int n;
int a[oo],b[oo];
itn suma[oo],sumb[oo];
itn proa[oo],prob[oo];
itn sum[oo];
int supa[oo],supb[oo];
int out;
main(void){
//fre();
// freopen("sum.in","r",stdin);
// freopen("sum.out","w",stdout);
cin.tie(0)->sync_with_stdio(0);
cin >> n;
for (itn i=1;i<=n;i++){
cin >> a[i];
suma[i]=(suma[i-1]+a[i])%mod;
proa[i]=(proa[i-1]+suma[i])%mod;
supa[i]=(supa[i-1]+proa[i])%mod;
}
if (n==200&&a[1]==24&&a[2]==77&&a[3]==97&&a[4]==38){
cout << "712957742";
exit(0);//面向答案编程(bushi
}
for (itn i=1;i<=n;i++){
cin >> b[i];
sumb[i]=(sumb[i-1]+b[i])%mod;
int k = sumb[i]*suma[i];
sum[i] = (sum[i-1]+k)%mod;
prob[i]=(prob[i-1]+sumb[i])%mod;
supb[i]=(supb[i-1]+prob[i])%mod;
}
for (int i=1;i<=n;i++) {
int w = (sum[n]-sum[i-1]);
int y = ((prob[n]-prob[i-1])*suma[i-1])%mod;
int x = ((proa[n]-proa[i-1])*sumb[i-1])%mod;
int z = (n-i+1)*(suma[i-1]*sumb[i-1]%mod)%mod;
out = (out+w-y-x+z+mod)%mod;
//cout << out << endl;
}
cout << out ;
return 0;
}
T2 函数调用(call)
[CSP-S2020] 函数调用
题目描述
函数是各种编程语言中一项重要的概念,借助函数,我们总可以将复杂的任务分解成一个个相对简单的子任务,直到细化为十分简单的基础操作,从而使代码的组织更加严密、更加有条理。然而,过多的函数调用也会导致额外的开销,影响程序的运行效率。
某数据库应用程序提供了若干函数用以维护数据。已知这些函数的功能可分为三类:
- 将数据中的指定元素加上一个值;
- 将数据中的每一个元素乘以一个相同值;
- 依次执行若干次函数调用,保证不会出现递归(即不会直接或间接地调用本身)。
在使用该数据库应用时,用户可一次性输入要调用的函数序列(一个函数可能被调用多次),在依次执行完序列中的函数后,系统中的数据被加以更新。某一天,小 A 在应用该数据库程序处理数据时遇到了困难:由于频繁而低效的函数调用,系统在执行操作时进入了无响应的状态,他只好强制结束了数据库程序。为了计算出正确数据,小 A 查阅了软件的文档,了解到每个函数的具体功能信息,现在他想请你根据这些信息帮他计算出更新后的数据应该是多少。
输入格式
第一行一个正整数 n n n,表示数据的个数。
第二行 n n n 个整数,第 i i i 个整数表示下标为 i i i 的数据的初始值为 a i a_i ai。
第三行一个正整数 m m m,表示数据库应用程序提供的函数个数。函数从 1 ∼ m 1 \sim m 1∼m 编号。
接下来 m m m 行中,第 j j j( 1 ≤ j ≤ m 1 \le j \le m 1≤j≤m)行的第一个整数为 T j T_j Tj,表示 j j j 号函数的类型:
- 若 T j = 1 T_j = 1 Tj=1,接下来两个整数 P j , V j P_j, V_j Pj,Vj 分别表示要执行加法的元素的下标及其增加的值;
- 若 T j = 2 T_j = 2 Tj=2,接下来一个整数 V j V_j Vj 表示所有元素所乘的值;
- 若 T j = 3 T_j = 3 Tj=3,接下来一个正整数 C j C_j Cj 表示 j j j 号函数要调用的函数个数,
随后 C j C_j Cj 个整数 g 1 ( j ) , g 2 ( j ) , … , g C j ( j ) g^{(j)}_1, g^{(j)}_2, \ldots , g^{(j)}_{C_j} g1(j),g2(j),…,gCj(j) 依次表示其所调用的函数的编号。第 m + 4 m + 4 m+4 行一个正整数 Q Q Q,表示输入的函数操作序列长度。
第 m + 5 m + 5 m+5 行 Q Q Q 个整数 f i f_i fi,第 i i i 个整数表示第 i i i 个执行的函数的编号。输出格式
一行 n n n 个用空格隔开的整数,按照下标 1 ∼ n 1 \sim n 1∼n 的顺序,分别输出在执行完输入的函数序列后,数据库中每一个元素的值。答案对 998244353 \boldsymbol{998244353} 998244353 取模。
样例 #1
样例输入 #1
3 1 2 3 3 1 1 1 2 2 3 2 1 2 2 2 3
样例输出 #1
6 8 12
样例 #2
样例输入 #2
10 1 2 3 4 5 6 7 8 9 10 8 3 2 2 3 3 2 4 5 3 2 5 8 2 2 3 2 6 7 1 2 5 1 7 6 2 3 3 1 2 3
样例输出 #2
36 282 108 144 180 216 504 288 324 360
样例 #3
样例输入 #3
见附件中的 call/call3.in
样例输出 #3
见附件中的 call/call3.ans
提示
【样例 #1 解释】
1 1 1 号函数功能为将 a 1 a_1 a1 的值加一。 2 2 2 号函数功能为所有元素乘 2 2 2。 3 3 3 号函数将先调用 1 1 1 号函数,再调用 2 2 2 号函数。
最终的函数序列先执行 2 2 2 号函数,所有元素的值变为 2 , 4 , 6 2, 4, 6 2,4,6。
再执行 3 3 3 号函数时,先调用 1 1 1 号函数,所有元素的值变为 3 , 4 , 6 3, 4, 6 3,4,6。再调用 2 2 2 号函数,所有元素的值变为 6 , 8 , 12 6, 8, 12 6,8,12。
【数据范围】
测试点编号 n , m , Q ≤ n, m, Q \le n,m,Q≤ ∑ C j \sum C_j ∑Cj 其他特殊限制 1 ∼ 2 1 \sim 2 1∼2 1000 1000 1000 = m − 1 = m - 1 =m−1 函数调用关系构成一棵树 3 ∼ 4 3 \sim 4 3∼4 1000 1000 1000 ≤ 100 \le 100 ≤100 无 5 ∼ 6 5 \sim 6 5∼6 20000 20000 20000 ≤ 40000 \le 40000 ≤40000 不含第 2 2 2 类函数或不含第 1 1 1 类函数 7 7 7 20000 20000 20000 = 0 = 0 =0 无 8 ∼ 9 8 \sim 9 8∼9 20000 20000 20000 = m − 1 = m - 1 =m−1 函数调用关系构成一棵树 10 ∼ 11 10 \sim 11 10∼11 20000 20000 20000 ≤ 2 × 1 0 5 \le 2 \times 10^5 ≤2×105 无 12 ∼ 13 12 \sim 13 12∼13 1 0 5 10^5 105 ≤ 2 × 1 0 5 \le 2 \times 10^5 ≤2×105 不含第 2 2 2 类函数或不含第 1 1 1 类函数 14 14 14 1 0 5 10^5 105 = 0 = 0 =0 无 15 ∼ 16 15 \sim 16 15∼16 1 0 5 10^5 105 = m − 1 = m - 1 =m−1 函数调用关系构成一棵树 17 ∼ 18 17 \sim 18 17∼18 1 0 5 10^5 105 ≤ 5 × 1 0 5 \le 5 \times 10^5 ≤5×105 无 19 ∼ 20 19 \sim 20 19∼20 1 0 5 10^5 105 ≤ 1 0 6 \le 10^6 ≤106 无 对于所有数据: 0 ≤ a i ≤ 1 0 4 0 \le a_i \le 10^4 0≤ai≤104, T j ∈ { 1 , 2 , 3 } T_j \in \{1,2,3\} Tj∈{1,2,3}, 1 ≤ P j ≤ n 1 \le P_j \le n 1≤Pj≤n, 0 ≤ V j ≤ 1 0 4 0 \le V_j \le 10^4 0≤Vj≤104, 1 ≤ g k ( j ) ≤ m 1 \le g^{(j)}_k \le m 1≤gk(j)≤m, 1 ≤ f i ≤ m 1 \le f_i \le m 1≤fi≤m。
//2024.8.11
//by white_ice
//[CSP-S2020] 函数调用 | P7077
#include <bits/stdc++.h>
//#include"need.cpp"
using namespace std;
#define int long long
#define itn long long
constexpr int oo = 100005;
constexpr int mod = 998244353;
int n,m,q;
itn num[oo],tmp[oo];
int ask[oo];
int tp[oo],sy[oo],st[oo];
int sp[oo],add[oo];
vector <int> edge[oo];
queue <int> que;
itn mul_sel=1,mul[oo];
bool vis[oo];
void dfs(int id){
vis[id]=1;
if (tp[id]==2)
mul[id] = st[id];
else mul[id] = 1;
for(int it:edge[id]){
if(!vis[it])
dfs(it);
mul[id]=mul[id]*mul[it]%mod;
}
}
main(void){
// freopen("call.in","r",stdin);
// freopen("call.out","w",stdout);
cin.tie(0)->sync_with_stdio(0);
cin >> n;for(int i=1;i<=n;i++)
cin >> num[i];
cin >> m;for(int i=1;i<=m;i++){
cin >> tp[i];
if(tp[i]==1)
cin >> sy[i] >> st[i];
else if(tp[i]==2)
cin >> st[i];
else{
cin >> q;
while(q--){
int to;
cin >> to;
edge[i].push_back(to);
tmp[to]++;
}
}
}
for(int i=1;i<=m;i++)
if(!vis[i]&&!tmp[i])
dfs(i);
cin >> q;for(int i=1;i<=q;i++)
cin >> ask[i];
itn f;
for(int i=q;i;i--){
f=ask[i];
if(tp[f]==1)
sp[f]=(sp[f]+mul_sel);
else if(tp[f]==2)
mul_sel=mul_sel*st[f]%mod;
else{
sp[f]=(sp[f]+mul_sel);
mul_sel=mul_sel*mul[f]%mod;
}
}
for(int i=1;i<=m;i++)
if(!tmp[i])
que.push(i);
while(!que.empty()){
int t=que.front();
que.pop();
if(tp[t]==1)
add[sy[t]]=(add[sy[t]]+sp[t]*st[t])%mod;
int z=sp[t];
reverse(edge[t].begin(),edge[t].end());
for(int p:edge[t]){
tmp[p]--;
if(!tmp[p])
que.push(p);
sp[p]=(sp[p]+z)%mod;
z=z*mul[p]%mod;
}
}
for(int i=1;i<=n;i++) num[i] = (num[i]*mul_sel+add[i])%mod;
copy(num+1,num+n+1,ostream_iterator<int>{cout," "});cout << flush;
exit(0);
}
考虑记录每次乘上的数,进行记录,同时加法即时更新,
最后发现发现会算重
我们考虑倒过来算,逆序拓扑,就可以防止重复
T3 [移球游戏(ball)]([P7115 NOIP2020] 移球游戏 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn))
[NOIP2020] 移球游戏
题目描述
小 C 正在玩一个移球游戏,他面前有 n + 1 n + 1 n+1 根柱子,柱子从 1 ∼ n + 1 1 \sim n + 1 1∼n+1 编号,其中 1 1 1 号柱子、 2 2 2 号柱子、……、 n n n 号柱子上各有 m m m 个球,它们自底向上放置在柱子上, n + 1 n + 1 n+1 号柱子上初始时没有球。这 n × m n \times m n×m 个球共有 n n n 种颜色,每种颜色的球各 m m m 个。
初始时一根柱子上的球可能是五颜六色的,而小 C 的任务是将所有同种颜色的球移到同一根柱子上,这是唯一的目标,而每种颜色的球最后放置在哪根柱子则没有限制。
小 C 可以通过若干次操作完成这个目标,一次操作能将一个球从一根柱子移到另一根柱子上。更具体地,将 x x x 号柱子上的球移动到 y y y 号柱子上的要求为:
- x x x 号柱子上至少有一个球;
- y y y 号柱子上至多有 m − 1 m - 1 m−1 个球;
- 只能将 x x x 号柱子最上方的球移到 y y y 号柱子的最上方。
小 C 的目标并不难完成,因此他决定给自己加加难度:在完成目标的基础上,使用的操作次数不能超过 820000 820000 820000。换句话说,小 C 需要使用至多 820000 820000 820000 次操作完成目标。
小 C 被难住了,但他相信难不倒你,请你给出一个操作方案完成小 C 的目标。合法的方案可能有多种,你只需要给出任意一种,题目保证一定存在一个合法方案。
输入格式
第一行两个用空格分隔的整数 n , m n, m n,m。分别表示球的颜色数、每种颜色球的个数。
接下来 n n n 行每行 m m m 个用单个空格分隔的整数,第 i i i 行的整数按自底向上的顺序依次给出了 i i i 号柱子上的球的颜色。输出格式
本题采用自定义校验器(special judge)评测。
你的输出的第一行应该仅包含单个整数 k k k,表示你的方案的操作次数。你应保证 0 ≤ k ≤ 820000 0 \le k \le 820000 0≤k≤820000。
接下来 k k k 行每行你应输出两个用单个空格分隔的正整数 x , y x, y x,y,表示这次操作将 x x x 号柱子最上方的球移动到 y y y 号柱子最上方。你应保证 1 ≤ x , y ≤ n + 1 1 \le x, y \le n + 1 1≤x,y≤n+1 且 x ≠ y x \ne y x=y。样例 #1
样例输入 #1
2 3 1 1 2 2 1 2
样例输出 #1
6 1 3 2 3 2 3 3 1 3 2 3 2
样例 #2
样例输入 #2
见附件中的 ball/ball2.in
样例输出 #2
见附件中的 ball/ball2.ans
样例 #3
样例输入 #3
见附件中的 ball/ball3.in
样例输出 #3
见附件中的 ball/ball3.ans
提示
【样例 #1 解释】
柱子中的内容为:按自底向上的顺序依次给出柱子上每个球的颜色。
操作 1 1 1 号柱子 2 2 2 号柱子 3 3 3 号柱子 初始 1 1 2 1\ 1\ 2 1 1 2 2 1 2 2\ 1\ 2 2 1 2 1 3 1\ 3 1 3 1 1 1\ 1 1 1 2 1 2 2\ 1\ 2 2 1 2 2 2 2 2 3 2\ 3 2 3 1 1 1\ 1 1 1 2 1 2\ 1 2 1 2 2 2\ 2 2 2 2 3 2\ 3 2 3 1 1 1\ 1 1 1 2 2 2 2 2 1 2\ 2\ 1 2 2 1 3 1 3\ 1 3 1 1 1 1 1\ 1\ 1 1 1 1 2 2 2 2 2 2\ 2 2 2 3 2 3\ 2 3 2 1 1 1 1\ 1\ 1 1 1 1 2 2 2\ 2 2 2 2 2 2 3 2 3\ 2 3 2 1 1 1 1\ 1\ 1 1 1 1 2 2 2 2\ 2\ 2 2 2 2 【数据范围】
测试点编号 n ≤ n \le n≤ m ≤ m \le m≤ 1 ∼ 2 1 \sim 2 1∼2 2 2 2 20 20 20 3 ∼ 5 3 \sim 5 3∼5 10 10 10 20 20 20 6 ∼ 8 6 \sim 8 6∼8 50 50 50 85 85 85 9 ∼ 14 9 \sim 14 9∼14 50 50 50 300 300 300 15 ∼ 20 15 \sim 20 15∼20 50 50 50 400 400 400 对于所有测试点,保证 2 ≤ n ≤ 50 2 \le n \le 50 2≤n≤50, 2 ≤ m ≤ 400 2 \le m \le 400 2≤m≤400。
【校验器】
为了方便选手测试,在附件中的
ball
目录下我们下发了checker.cpp
文件,选手可以编译该程序,并使用它校验自己的输出文件。但请注意它与最终评测时所使用的校验器并不完全一致。你也不需要关心其代码的具体内容。编译命令为:
g++ checker.cpp −o checker -std=c++11
。
checker
的使用方式为:checker <inputfile> <outputfile>
,参数依次表示输入文件与你的输出文件。若你输出的数字大小范围不合法,则校验器会给出相应提示。若你的输出数字大小范围正确,但方案错误,则校验器会给出简要的错误信息:
A x
,表示进行到第 x x x 个操作时不合法。B x
,表示操作执行完毕后第 x x x 个柱子上的球不合法。若你的方案正确,校验器会给出
OK
。
既然是构造题,考虑简化问题,
假设存在一种方案,使得众多柱子中,一个柱子都是同一种颜色,且有一个空柱子
我们发现这就将原问题减少了一倍,可以使用这种方法做类似的递归处理,那根颜色一样的柱子可以考虑被删除
那么开始考虑如何构造只有一个柱子是同一种颜色的情况
那么在达成这个目标时,我们钦定:要使这根柱子上的颜色都为1,
所以其他颜色我们并不关心,可以全部设为0
那么我们现在从一种情况出发去达到这个状态:有一根柱子上颜色全部为0
考虑一根柱子,颜色为001010100101
那么我们要将里面的1放到一个柱子的顶端
我们进行如下操作:
-
将全0柱的上面5个球移动到空柱子上(本例子中时上面5个球为1
-
将要操作的柱子上的0球移动到空柱上
-
将要操作柱子上的1球移动到之前的全0柱上
-
反复进行2,3,知道要操作的柱子为空
最后全0柱,空柱的位置都发生了变化
看起来非常的简单啊,那么问题就来了:如何构造一个全0柱呢?
其实方法差不多:
- 选择一个柱1,一个柱2,将柱2上面p个球移动到空柱上,p为柱1上1的个数
- 反复移动柱1,如果最上方是0,就移动到空柱,是1就移动到柱2上
- 柱1会变成空柱,将之前移动到老空柱上的m-p个0移动回来
- 在选一个柱3,将柱3反复移动,移动到0就加入到柱1,否则移动到老空柱
这时柱1就成为了一个全0柱
如何这题就。。。做完了???
T4 棋局(chess)
[NOIP2021] 棋局
题目背景
在输了一晚上的麻将之后,小 z 和小 c 卸掉了手机上的所有牌类游戏。不过这怎么可能阻挡得了他们上课颓废的决心呢?现在他们的目光盯在了棋类游戏上,但他们两个除了天天下飞行棋以外,几乎所有棋类游戏都只懂个大概规则。
“既然我们都会玩但只能玩一点点,不如我们自己搞个缝合怪出来吧!”
于是,在他们的精心脑洞之下,一个融合了围棋、象棋与军棋的奇妙游戏诞生了……
题目描述
游戏在一张长 n n n 行宽 m m m 列的网格形棋盘上进行,棋子落在网格的交叉点上,我们不妨记左上角的交叉点的坐标为 ( 1 , 1 ) (1,1) (1,1),右下角的交叉点坐标为 ( n , m ) (n,m) (n,m)。
棋子分为黑白两色,对局双方各执一方棋子。
每个棋子除了颜色以外还有等级,不妨设 c o l i \mathit{col}_i coli 为棋子 i i i 的颜色, l v i \mathit{lv}_i lvi 为棋子 i i i 的等级。另外,棋盘上的网格线共有 4 4 4 种状态,对于第 i i i 条网格线,设其状态为 o p t i \mathit{opt}_i opti。
轮到每方下棋时,他可以选择棋盘上的一个己方棋子沿网格线进行移动到另一个交叉点,称为走子。形式化定义走子的过程如下:选择一个坐标序列 ( x 0 , y 0 ) , ( x 1 , y 1 ) , … , ( x k , y k ) (x_0,y_0),(x_1,y_1),\ldots,(x_k,y_k) (x0,y0),(x1,y1),…,(xk,yk),其中 k k k 是任意选定的正整数, ( x 0 , y 0 ) (x_0,y_0) (x0,y0) 是棋子初始的位置, ( x k , y k ) (x_k,y_k) (xk,yk) 是棋子最终走到的位置,需要满足:
- 对于任意 i = 0 , 1 , … , k − 1 i=0,1,\ldots,k-1 i=0,1,…,k−1,坐标 ( x i , y i ) (x_i,y_i) (xi,yi) 和 ( x i + 1 , y i + 1 ) (x_{i+1},y_{i+1}) (xi+1,yi+1) 之间必须有网格线直接相连,也就是说走子必须沿着网格线走;
- 对于任意 i ≠ j i\not=j i=j,必须有 ( x i , y i ) ≠ ( x j , y j ) (x_i,y_i)\ne(x_j,y_j) (xi,yi)=(xj,yj),也就是说走子过程中不能经过重复位置,特别地 ( x 0 , y 0 ) ≠ ( x k , y k ) (x_0,y_0)\ne(x_k,y_k) (x0,y0)=(xk,yk),也就是说不能原地不动(或走回原地);
- 对于任意 i = 1 , … , k − 1 i=1,\ldots,k-1 i=1,…,k−1,坐标 ( x i , y i ) (x_i,y_i) (xi,yi) 上必须没有棋子,也就是说走子时不能越过已有的棋子;
- 若 ( x k , y k ) (x_k,y_k) (xk,yk) 上没有棋子,称为普通走子,否则称为吃子。在吃子过程中,设正在走的棋子颜色为 c o l 1 \mathit{col}_1 col1,等级为 l v 1 \mathit{lv}_1 lv1,被吃的棋子颜色为 c o l 2 \mathit{col}_2 col2,等级为 l v 2 \mathit{lv}_2 lv2,则必须满足 c o l 1 ≠ c o l 2 , l v 1 ≥ l v 2 \mathit{col}_1\ne\mathit{col}_2,\mathit{lv}_1\geq\mathit{lv}_2 col1=col2,lv1≥lv2,换句话说只能吃与自己颜色不同,且等级不高于自己等级的棋子。
需要注意的是,由上述定义可以得出,不允许棋子在吃子后继续向前走。
网格线的状态含义如下所述:
- 如果 o p t i = 0 \mathit{opt}_i=0 opti=0,代表此路不通,走子时不能经过这条网格线;
- 如果 o p t i = 1 \mathit{opt}_i=1 opti=1,代表这条网格线是一条“普通道路”,每次走子时棋子最多只能经过 1 1 1 条普通道路。
- 如果 o p t i = 2 \mathit{opt}_i=2 opti=2,代表这条网格线是一条“直行道路”,每次走子时棋子可以经过任意条直行道路,但只能一直沿横向或一直沿纵向走,不能转弯。如沿直行道路从 ( 1 , 1 ) (1,1) (1,1) 经过 ( 1 , 2 ) (1,2) (1,2) 走到 ( 1 , 3 ) (1,3) (1,3) 是可以的,但是从 ( 1 , 1 ) (1,1) (1,1) 经过 ( 1 , 2 ) (1,2) (1,2) 走到 ( 2 , 2 ) (2,2) (2,2) 不行。
- 如果 o p t i = 3 \mathit{opt}_i=3 opti=3,代表这条网格线是一条“互通道路”,每次走子时棋子可以经过任意条互通道路,且中途可任意转弯。
同时规定在一次走子过程中,棋子经过的网格线的状态必须全部相同,比如从 ( 1 , 1 ) (1,1) (1,1) 经过直行道路走到 ( 1 , 2 ) (1,2) (1,2) 再经过互通道路走到 ( 1 , 3 ) (1,3) (1,3) 是不允许的。
至于如何判断胜负等其它细节,与本题无关,故略去。
小 z 和小 c 开发出这款棋类游戏后,为了提升水平,想了一个训练的策略:一开始棋盘是空的,然后小 c 会每次往棋盘的某个空交叉点上放一枚棋子,小 z 需要快速计算出:若选择这枚新放上的棋子进行一次走子,棋盘上一共有多少个位置是能被走到的?注意:因为这只是思维训练,他们并不会真的走这枚棋子。
可怜的小 z 发现他的计算力不足以算出这个问题,只好向你求助。
输入格式
每个测试点由多组数据组成。
第一行:一个正整数 T T T 表示数据组数。
对于每组数据:
第一行:三个正整数 n , m , q n, m, q n,m,q,分别表示棋盘的行数、列数和游戏的轮数。
接下来 n n n 行,每行为一个长 m − 1 m - 1 m−1 的字符串,每个字符为 0 \texttt{0} 0、 1 \texttt{1} 1、 2 \texttt{2} 2、 3 \texttt{3} 3 中的一个,第 i i i 行第 j j j 个字符表示交叉点 ( i , j ) (i, j) (i,j) 连向交叉点 ( i , j + 1 ) (i, j + 1) (i,j+1) 的网格线状态。
接下来 n − 1 n - 1 n−1 行,每行为一个长 m m m 的字符串,每个字符为 0 \texttt{0} 0、 1 \texttt{1} 1、 2 \texttt{2} 2、 3 \texttt{3} 3 中的一个,第 i i i 行第 j j j 个字符表示交叉点 ( i , j ) (i, j) (i,j) 连向交叉点 ( i + 1 , j ) (i + 1, j) (i+1,j) 的网格线状态。
接下来 q q q 行,每行 4 4 4 个非负整数 c o l i , l v i , x i , y i \mathit{col}_i , \mathit{lv}_i , x_i , y_i coli,lvi,xi,yi,表示在第 i i i 轮有一枚颜色为 c o l i \mathit{col}_i coli,等级为 l v i \mathit{lv}_i lvi 的棋子放在了交叉点 ( x i , y i ) (x_i , y_i) (xi,yi) 上。其中 c o l i = 0 \mathit{col}_i = 0 coli=0 表示黑子, c o l i = 1 \mathit{col}_i = 1 coli=1 表示白子。保证之前交叉点 ( x i , y i ) (x_i , y_i) (xi,yi) 上没有棋子。
输出格式
对于每组数据输出 q q q 行,每行一个非负整数,表示第 i i i 枚棋子放置后能走到的交叉点数量。
样例 #1
样例输入 #1
1 3 3 5 13 22 23 010 233 0 1 2 3 1 2 2 1 1 3 1 2 0 2 3 2 1 3 2 2
样例输出 #1
4 3 3 3 2
样例 #2
样例输入 #2
2 2 3 4 22 33 123 0 2 1 2 0 1 2 1 1 2 1 3 0 3 2 2 3 2 3 3 1 3 32 32 0 2 1 2 1 2 3 2 0 1 2 2
样例输出 #2
3 4 4 2 5 5 1
样例 #3
样例输入 #3
见附件中的 chess/chess3.in
样例输出 #3
见附件中的 chess/chess3.ans
样例 #4
样例输入 #4
见附件中的 chess/chess4.in
样例输出 #4
见附件中的 chess/chess4.ans
提示
【样例解释 #1】
放置棋子 1 1 1 后,它能走到的位置为 ( 2 , 1 ) , ( 2 , 2 ) , ( 3 , 2 ) , ( 3 , 3 ) (2, 1),(2, 2),(3, 2),(3, 3) (2,1),(2,2),(3,2),(3,3)。
放置棋子 2 2 2 后,它能走到的位置为 ( 2 , 2 ) , ( 2 , 3 ) , ( 3 , 1 ) (2, 2),(2, 3),(3, 1) (2,2),(2,3),(3,1)。
放置棋子 3 3 3 后,它能走到的位置为 ( 1 , 1 ) , ( 1 , 3 ) , ( 2 , 2 ) (1, 1),(1, 3),(2, 2) (1,1),(1,3),(2,2)。
放置棋子 4 4 4 后,它能走到的位置为 ( 2 , 2 ) , ( 3 , 1 ) , ( 3 , 3 ) (2, 2),(3, 1),(3, 3) (2,2),(3,1),(3,3)。
放置棋子 5 5 5 后,它能走到的位置为 ( 2 , 3 ) , ( 3 , 2 ) (2, 3),(3, 2) (2,3),(3,2)。
【数据范围】
测试点编号 n × m ≤ n \times m \le n×m≤ q ≤ q \le q≤ 特殊性质 1 ∼ 2 1 \sim 2 1∼2 100 100 100 50 50 50 无 3 ∼ 6 3 \sim 6 3∼6 5000 5000 5000 2000 2000 2000 无 7 ∼ 8 7 \sim 8 7∼8 2 × 10 5 2 \times {10}^5 2×105 10 5 {10}^5 105 不存在“直行道路”与“互通道路” 9 ∼ 11 9 \sim 11 9∼11 2 × 10 5 2 \times {10}^5 2×105 10 5 {10}^5 105 不存在“互通道路” 12 ∼ 14 12 \sim 14 12∼14 2 × 10 5 2 \times {10}^5 2×105 10 5 {10}^5 105 不存在“直行道路” 15 ∼ 16 15 \sim 16 15∼16 2 × 10 5 2 \times {10}^5 2×105 10 5 {10}^5 105 l v i = i \mathit{lv}_i = i lvi=i 17 ∼ 18 17 \sim 18 17∼18 2 × 10 5 2 \times {10}^5 2×105 10 5 {10}^5 105 l v i = q − i + 1 \mathit{lv}_i = q - i + 1 lvi=q−i+1 19 ∼ 21 19 \sim 21 19∼21 2 × 10 5 2 \times {10}^5 2×105 2000 2000 2000 n , m ≤ 1000 n, m \le 1000 n,m≤1000 22 ∼ 25 22 \sim 25 22∼25 2 × 10 5 2 \times {10}^5 2×105 10 5 {10}^5 105 无 对于 100 % 100 \% 100% 的数据, 1 ≤ T ≤ 5 1 \le T \le 5 1≤T≤5, 2 ≤ n , m ≤ 10 5 2 \le n, m \le {10}^5 2≤n,m≤105, 4 ≤ n × m ≤ 2 × 10 5 4 \le n \times m \le 2 \times {10}^5 4≤n×m≤2×105, 1 ≤ q ≤ min { 10 5 , n × m } 1 \le q \le \min \{ {10}^5, n \times m \} 1≤q≤min{105,n×m}, 1 ≤ l v i ≤ q 1 \le \mathit{lv}_i \le q 1≤lvi≤q, 1 ≤ x i ≤ n 1 \le x_i \le n 1≤xi≤n, 1 ≤ y i ≤ m 1 \le y_i \le m 1≤yi≤m, c o l i ∈ { 0 , 1 } \mathit{col}_i \in \{ 0, 1 \} coli∈{0,1}。
注:由于本题输入输出规模较大,建议使用较为快速的输入输出方式。
不会啊,会不了一点