随机化算法
Kazaee
有一个长度为n的数组,区间询问所有数的出现次数是不是k的倍数
考虑将a进行随即映射操作,如果【l,r】的和不是S的倍数那么答案一定是NO,否则可能是YES
多进行几次映射
Code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define inf 0x3f3f3f3f
#define N 300005
#define lb(x) ((x)&-(x))
int n,q;
int a[N],b[N];
int op[N],l[N],r[N],k[N];
int num[N<<1],tot;
int R[N<<1];
int ans[N];
int bit[N];
mt19937 rd(time(0));
inline void upd(int p,int v){
while(p<=n){
bit[p]+=v;
p+=lb(p);
}
}
inline int qry(int p){
int s=0;
while(p){
s+=bit[p];
p-=lb(p);
}
return s;
}
inline int qry(int L,int R){
return qry(R)-qry(L-1);
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>q;
for(int i=1;i<=n;++i){
cin>>a[i];
num[++tot]=a[i];
}
for(int i=1;i<=q;++i){
cin>>op[i]>>l[i]>>r[i];
ans[i]=1;
if(op[i]==2)cin>>k[i];
else num[++tot]=r[i];
}
sort(num+1,num+tot+1);
tot=unique(num+1,num+tot+1)-num-1;
for(int i=1;i<=n;++i){
a[i]=lower_bound(num+1,num+tot+1,a[i])-num;
}
for(int i=1;i<=q;++i){
if(op[i]==1){
r[i]=lower_bound(num+1,num+tot+1,r[i])-num;
}
}
for(int t=1;t<=30;++t){
for(int i=1;i<=n;++i)bit[i]=0;
for(int i=1;i<=n;++i)b[i]=a[i];
for(int i=1;i<=tot;++i)R[i]=rd()>>1;
for(int i=1;i<=n;++i){
upd(i,R[b[i]]);
}
for(int i=1;i<=q;++i){
if(op[i]==1){
upd(l[i],R[r[i]]-R[b[l[i]]]);
b[l[i]]=r[i];
}else{
if(ans[i]){
if((r[i]-l[i]+1)%k[i]){
ans[i]=0;
continue;
}
if(qry(l[i],r[i])%k[i]){
ans[i]=0;
continue;
}
}
}
}
}
for(int i=1;i<=q;++i){
if(op[i]==2){
if(ans[i])cout<<"YES\n";
else cout<<"NO\n";
}
}
return 0;
}
P10102
多测,问\(A\times B\)是否等于C,均为大小为\(n\times n\)的矩阵
随机一个 n×1 的向量 \(x\),检验 \(A×B×x\) 和 \(C×x\) 是否相等即可
P1224d
问n个d维度向量是否存在(x,y)为k的倍数
考虑k=2怎么做,将向量排列为\(n\times d\)的矩阵
考虑如果将\(A\)和\(A^T\)相乘得到\(B\),如果\(B_{i,j}=0\),答案即为\(i,j\)
随机构造一个 n 行列向量 R。如果 B 是一个全 1 矩阵,那么 B×R 得到的列向量的每个元素都应该是 R 中的所有元素和,且如果第 i 行不满足,那么肯定存在一组 i,j 是答案
\(B\times R=(A\times(A^T\times R))\)
考虑k=3怎么做,发现mod 3意义下1和2的平方都是1
考虑 check 矩阵 B 的每个值平方后是否是全 1 矩阵
随机生成数组r,考虑\(\sum_j B_{i,j}^2 r_j\)是否等于\(\sum_j r_j\)
其中 R 是一个只有对角线有值的矩阵,有\(R_{j,j}=r_j\)
\(B\times R\times B^T=A\times (A^T\times (R\times A))\times A^T\)
能够bitset优化
E[JSOI2016]炸弹攻击
平面上有若干个圆,还有若干个点,选择一个圆(不是图中的),不和图中的圆相交,问最多包括多少点
对于一个点 (x,y),先计算出在不碰到建筑物的限制下能取的最大半径,然后通过这个半径容易算出可以杀死多少个敌人
考虑对于(x,y)进行模拟退火
考虑设一个返回值为实数的平滑的函数,能对「即使当前点杀死敌人数量是 0,那么它离 1 有多近」有良好的参考
考虑「当前点对应的最大半径还需再增加多少能碰到第一个敌人」,将这个量看作\(r_0\),作为一个参考量
要么r_0=0
CF1641D
n个数组a,还有一个数组
问所有数对中\(w_{i,j}\)的最小值,要求两列的数两两不同
FMT就先不做了
对于 O(n×m) 种权值,每种权值开一个 n 位的 bitset,表示权值 c 是否出现在第 i 个数组中
将n个数组以\(w_i\)为关键字排序
枚举数组对 (i,j) 中的 j,找一个最小的 i 与之匹配
将数组 j 内的元素的 bitset 或起来并反转每个位
找最低位的 1 的位置
P7606
等边三角形组成的网格图,最初在源点,每次操作会在网格图是行移动一定的距离,对应图中的6个移动方式,并且会让L和G的值加上一些
网格图最终n次操作后需要回到原点
问能否让位置到达某处
变成沿 x 轴,沿 y 轴,沿 y=x 的三条线
考虑\(dp_{i,j,k,l,g}\)前 i 个数,当前横坐标在 j,当前纵坐标在 k,当前 L 是 l,当前 G 是 g 是否可行
考虑只用bitset优化,无法通过
考虑非常经典的随机游走问题,它告诉我们在二维平面上每次随机选一个方向走 1 的单位长度,走 n 步期望的距离不会超过 根号n级别:
这道题我们选择的方案也可以当成是随机在 6 种当中选 1 种出来
P5406
定义一种新运算是按位随意选择与/或/非(题面给定)
一张 n 个点 m 条边的无向图,每一条边的权值是一个 w 位二进制数,找一棵原图的生成树
最大化
不是一道最优化题,这是一道计数题,如果对每个 i,我们求出权值为 i 的生成树的数量,那么答案就是最大的生成树数量不为 0 的 i
首先矩阵树定理
注意到这个 ∏,它不一定非得是数相乘,只要保证 <W,+,×> 构成一个环,那么这个式子就成立。其中 W 是边权所在的全集
构造函数
FWT后IFWT

浙公网安备 33010602011771号