NOI模拟18
T2 亿点整理
看到排列+矩阵就想行列式吧,当然前两天有一个是容斥
这个把\(f_{i,j}\)放到矩阵的指数上就可以实现乘法化,变成\(x^{f_{i,j}}\),这样我只要看\(x^{ik}\)有没有系数就行了
此时我们要求的是积和式,也就是行列式去掉-1的几次方,然而我们只需要判断有没有,那么就用行列式再rand个权值就行了
发现不能直接求多项式,所以用拉格朗日插值,并且我们让多项式指数mod k,用原根实现循环卷积就行了
多随机几个,卡个时,就可以出解了
AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
return s*t;
}
const int N=105;
int n,m,f[N][N],mod,g;
int ksm(int x,int y,int mo=mod){
if(y<0)return 0;
int ret=1;
while(y){
if(y&1)ret=ret*x%mo;
x=x*x%mo;y>>=1;
}return ret;
}
bool isp(int x){
for(int i=2;i*i<=x;i++)if(x%i==0)return false;
return true;
}
int ji[N],cj;
int findrt(){
int ph=mod-1;
for(int i=2;i*i<=ph;i++){
if(ph%i==0)ji[++cj]=i;
while(ph%i==0)ph/=i;
}ph=mod-1;
fo(i,2,mod){
bool flag=true;
fo(j,1,cj)if(ksm(i,ph/ji[j])==1){flag=false;break;}
if(flag)return i;
}return 0;
}
int a[N][N];
int gs(){
int ret=1;
fo(i,1,n){
if(!a[i][i]){
fo(j,i+1,n)if(a[j][i]){
fo(k,i,n)swap(a[i][k],a[j][k]);
ret=mod-ret;break;
}
}
fo(j,i+1,n)if(a[j][i]){
int t=a[j][i]*ksm(a[i][i],mod-2)%mod;
fo(k,i,n)a[j][k]=(a[j][k]-a[i][k]*t%mod+mod)%mod;
}
}fo(i,1,n)ret=ret*a[i][i]%mod;
return ret;
}
random_device you;
mt19937 pyt(20050223);
int rd(int l,int r){return uniform_int_distribution<>(l,r)(pyt);}
int x[N],y[N],rnd[N][N];
int get(){
fo(i,1,n)fo(j,1,n){
rnd[i][j]=rd(1,mod-1);
// cerr<<rnd[i][j]<<endl;
}
fo(o,0,m-1){
fo(i,1,n)fo(j,1,n)a[i][j]=rnd[i][j]*ksm(x[o],f[i][j])%mod;
y[o]=gs();
}int ret=0;
fo(i,0,m-1){
int fz=1,fm=1;
fo(j,0,m-1)if(i!=j){
fz=fz*(mod-x[j])%mod;
fm=fm*(x[i]-x[j]+mod)%mod;
}
ret=(ret+fz*ksm(fm,mod-2)%mod*y[i])%mod;
}return ret;
}
signed main(){
freopen("sort.in","r",stdin);
freopen("sort.out","w",stdout);
n=read();m=read();
fo(i,1,n)fo(j,1,n){
f[i][j]=read();
}
for(mod=m*m+1;!isp(mod);mod+=m);
g=findrt();
// cerr<<mod<<" "<<g<<endl;
x[0]=1;x[1]=ksm(g,(mod-1)/m);
fo(i,2,m-1)x[i]=x[i-1]*x[1]%mod;
while(1.0*clock()/CLOCKS_PER_SEC<1.5){
if(get()){printf("Yes");return 0;}
}printf("No");
return 0;
}
T3 亿块田
吉司机线段树,神了!!
如果普通线段树不能维护,我们可以考虑对每次的修改找到一个临界值,一边是可以直接修改的,另一边是需要继续递归的
于是我们可以进行一个势能分析,然后找到正确的复杂度
这里就是利用了变换之后大小关系不变的原理,分析一下就行了!!
AC_code
#include<bits/stdc++.h>
using namespace std;
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
return s*t;
}
const int N=2e5+5;
int n,m,a[N],u;
struct XDS{
#define ls x<<1
#define rs x<<1|1
int mx[N*4],ad[N*4],ar[N*4],td[N*4],tr[N*4];
void pushup(int x){
mx[x]=max(mx[ls],mx[rs]);
ad[x]=ad[ls]&ad[rs];
ar[x]=ar[ls]|ar[rs];
}
void pushd(int x,int v){
mx[x]&=v;
ad[x]&=v;ar[x]&=v;
td[x]&=v;tr[x]&=v;
}
void pushr(int x,int v){
mx[x]|=v;
ad[x]|=v;ar[x]|=v;
tr[x]|=v;
}
void pushdown(int x){
if(td[x]!=u){pushd(ls,td[x]);pushd(rs,td[x]);td[x]=u;}
if(tr[x]){pushr(ls,tr[x]);pushr(rs,tr[x]);tr[x]=0;}
}
void build(int x,int l,int r){
td[x]=u;tr[x]=0;
if(l==r)return ad[x]=ar[x]=mx[x]=a[l],void();
int mid=l+r>>1;
build(ls,l,mid);build(rs,mid+1,r);
pushup(x);
}
void ins_td(int x,int l,int r,int ql,int qr,int v){
if(ql<=l&&r<=qr){
if((ad[x]&(u^v))==(ar[x]&(u^v))){
pushd(x,v);return ;
}
}
int mid=l+r>>1;pushdown(x);
if(ql<=mid)ins_td(ls,l,mid,ql,qr,v);
if(qr>mid)ins_td(rs,mid+1,r,ql,qr,v);
pushup(x);
}
void ins_tr(int x,int l,int r,int ql,int qr,int v){
if(ql<=l&&r<=qr){
if((ad[x]&v)==(ar[x]&v)){
pushr(x,v);return ;
}
}
int mid=l+r>>1;pushdown(x);
if(ql<=mid)ins_tr(ls,l,mid,ql,qr,v);
if(qr>mid)ins_tr(rs,mid+1,r,ql,qr,v);
pushup(x);
}
int qry(int x,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr)return mx[x];
int mid=l+r>>1,ret=0;pushdown(x);
if(ql<=mid)ret=max(ret,qry(ls,l,mid,ql,qr));
if(qr>mid)ret=max(ret,qry(rs,mid+1,r,ql,qr));
pushup(x);return ret;
}
#undef ls
#undef rs
}xds;
signed main(){
freopen("farm.in","r",stdin);
freopen("farm.out","w",stdout);
n=read();m=read();u=(1<<20)-1;
fo(i,1,n)a[i]=read();
xds.build(1,1,n);
while(m--){
int tp=read(),l=read(),r=read(),v;
if(tp==1){v=read();xds.ins_td(1,1,n,l,r,v);}
if(tp==2){v=read();xds.ins_tr(1,1,n,l,r,v);}
if(tp==3){printf("%d\n",xds.qry(1,1,n,l,r));}
}
return 0;
}
QQ:2953174821