姓名:王胤皓,校区:和谐校区,考试时间: 2024 2024 2024 年 10 10 10 月 4 4 4 日 9 : 00 : 00 9:00:00 9:00:00~ 12 : 30 : 00 12:30:00 12:30:00,学号: S 07738 S07738 S07738
请关注作者的 B 站,谢谢~链接
CSP-J Day 4 4 4 模拟赛补题报告
前言
考了我们班 Rank 1 1 1。
分数
T1 three:
A
c
c
e
p
e
t
e
d
100
\color{green}Accepeted\space100
Accepeted 100
T2 fit:
A
c
c
e
p
e
t
e
d
100
\color{green}Accepeted\space100
Accepeted 100
T3 matrix:
T
L
E
20
\color{orange}TLE\space20
TLE 20
T4 pair:
T
L
E
20
\color{orange}TLE\space20
TLE 20
T1
题面
思路
打标找规律。
赛时 A c c e p e t e d \color{green}{Accepeted} Accepeted 代码
#include<bits/stdc++.h>
using namespace std;
int main(){
freopen("three.in","r",stdin);
freopen("three.out","w",stdout);
int n;
cin>>n;
n%=3;
if(n==0){
printf("odd\nodd\nodd\n");
}
else if(n==1){
printf("odd\nodd\neven\n");
}
else{
printf("even\neven\nodd\n");
}
return 0;
}
T2
题面
思路
开桶数组,然后利用递推,预处理。
代码
#include<bits/stdc++.h>
using namespace std;
int n,m,tong[1000005],q,x;
int main(){
freopen("fit.in","r",stdin);
freopen("fit.out","w",stdout);
cin.tie(0);
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=1; i<=n; i++){
int x;
cin>>x;
tong[x]++;
}
for(int i=1; i<=m; i++) tong[i]+=tong[i-1]/2;
cin>>q;
while(q--){
cin>>x;
cout<<tong[x]<<"\n";
}
return 0;
}
T3
题面
思路
枚举完起始行和终止行之后,还需要去计算结果,这一部分可以考虑优化。
可以按位去考虑,对于某个区间,按位异或之后的值,的某一位,是否为
1
1
1。只需要考虑这个区间内的这一位的
1
1
1 的个数是奇数个还是偶数个。
也可以考虑
x
o
r
xor
xor 数组
a
n
s
+
(
x
o
r
r
⊕
x
o
r
l
−
1
)
ans + (xor_r \oplus xor_{l-1})
ans+(xorr⊕xorl−1) ,按位考虑,某一位如果想被累计到答案里,那么
x
o
r
r
xor_r
xorr 的这一位和
x
o
r
l
−
1
xor_{l-1}
xorl−1 的这一位,不相同。所以可以考虑把
x
o
r
xor
xor 拆位,如果当前这一位是
1
1
1,那么就考虑它前面这一位是
0
0
0 的情况有多少个,反之同理。
代码
#include<bits/stdc++.h>
using namespace std;
int b[305][305],c[305],sum[305];
int main(){
cin.tie(0);
ios::sync_with_stdio(false);
int n,m;
cin>>n>>m;
long long cnt=0ll;
for(int i=1; i<=n; i++){
for(int j=1; j<=m; j++){
cin>>b[i][j];
}
}
long long ans=0;
for(int u=1; u<=n; u++){
memset(c,0,sizeof c);
memset(sum,0,sizeof sum);
for(int d=u;d<=n; d++){
for(int j=1; j<=m; j++){
c[j]^=b[d][j];
sum[j]=c[j]^sum[j-1];
}
for(int p=0;p<10;p++){
int cnt[2]={1,0};
for(int j=1; j<=m; j++){
int t=(sum[j]>>p)&1;
ans+=(1<<p)*cnt[t^1];
cnt[t]++;
}
}
}
}
cout<<ans<<"\n";
return 0;
}
T4
题面
思路
具体看代码中的注释
代码
#include<bits/stdc++.h>
using namespace std;
int a[1000005],b[1000005],cntb[15];
__int128 res[15],vis[15],cnt;
void print(__int128 ans){
if(ans==0) return;
print(ans/10);
putchar(ans%10+'0');
}
int main(){
cin.tie(0);
ios::sync_with_stdio(false);
int n,m,p;
cin>>n>>m>>p;
for(int i=1; i<=n; i++) cin>>a[i];
for(int i=1; i<=m; i++) cin>>b[i],cntb[b[i]]++;
if(p==1){
cout<<0<<"\n";
return 0;
}
for(int k=0;k<p;k++){
memset(vis,0,sizeof vis);
for(int i=1; i<=m; i++){
for(int j=b[i]+1; j<=p-1; j++){
res[k]+=vis[j];//$res_k$ 表示 $b$ 数组加上 $k$ 后,逆序对的数量
}
vis[b[i]]++;
b[i]=(b[i]+1)%p;
}
}
memset(vis,0,sizeof vis);//$vis$ 数组统计之前块中,每个数的出现次数
for(int i=1; i<=n; i++){
cnt+=res[a[i]];//统计块内逆序对的数量
for(int k=0;k<p;k++){//遍历 $b$ 中所有数字的取值
for(int j=(a[i]+k)%p+1; j<p;j++){
cnt+=cntb[k]*vis[j];//$b$ 序列中,$k$ 的数量,乘以之前块中比 $(a_i+k)\bmod p$ 大的数字个数
}
}
for(int k=0;k<p;k++){//遍历 $b$ 中所有数字的取值
vis[(a[i]+k)%p]+=cntb[k];//记录数量。
}
}
print(cnt);
return 0;
}