20210628模拟赛

数学场,体验感极好(捕获一只热爱数学的yxy

这是到目前为止除了 ASDFZ 的第一套以外考过的最难的一套模拟了

然后发现是我母亲的母校出的题 CDQZ yyds

T1 数论,T2 生成函数,T3 计数

感觉补完题后最有收获的是 T2,好好分析一波


T1

好题

分析

形式化的答案就是
∑ b ( b + c ) ≤ n 2 , c ≤ 3 b [ b ( b + c ) ∈ N ] b ( b + c ) \sum_{b(b+c)\le n^2,c\le 3b}[\sqrt{b(b+c)}\in N]\sqrt{b(b+c)} b(b+c)n2,c3b[b(b+c) N]b(b+c)
考虑 g c d ( b , c ) = 1 gcd(b,c)=1 gcd(b,c)=1 的情况,此时 b b b 一定是一个平方数,于是令 b = x 2 , a = x y , c = y 2 − x 2 b=x^2,a=xy,c=y^2-x^2 b=x2,a=xy,c=y2x2

代入不等式得到 y 2 − x 2 < 3 x 2 → y < 2 x y^2-x^2<3x^2 \to y<2x y2x2<3x2y<2x

所以 g c d ( b , c ) = 1 gcd(b,c)=1 gcd(b,c)=1 的答案就是
∑ x y ≤ n , g c d ( x , y ) = 1 , x < y < 2 x x y \sum_{xy\le n,gcd(x,y)=1,x<y<2x} xy xyn,gcd(x,y)=1,x<y<2xxy
如果 g c d ( b , c ) ≠ 1 gcd(b,c)\ne 1 gcd(b,c)=1 ,可以把 b , c b,c b,c 化成互质,然后答案 × g c d ( a , b ) \times gcd(a,b) ×gcd(a,b) ,令 S ( x ) = ∑ i = 1 x i S(x)=\sum_{i=1}^xi S(x)=i=1xi

那么总的答案就是
∑ x y ≤ n , g c d ( x , y ) = 1 , x < y < 2 x x y S ( n / x y ) \sum_{xy\le n,gcd(x,y)=1,x<y<2x} xyS(n/xy) xyn,gcd(x,y)=1,x<y<2xxyS(n/xy)
看着这个 g c d gcd gcd 就很烦,所以把它反演掉
∑ t μ ( t ) ∑ x y ≤ n / t 2 , x < y < 2 x x y t 2 S ( n / t 2 x y ) \sum_t\mu(t)\sum_{xy\le n/t^2,x<y<2x} xyt^2S(n/t^2xy) tμ(t)xyn/t2,x<y<2xxyt2S(n/t2xy)
这个式子可以整除分块,具体来说,第一维对 t t t 整除分块,然后枚举 x x x ,最后对 y y y 整除分块。可以做到 O ( n 2 / 3 ) O(n^{2/3}) O(n2/3)。感性理解一下复杂度, t t t 变大一点点后面的 x , y x,y x,y 的范围就会大幅度变小,所以远远跑不到 O ( n ) O(n) O(n) 的。

#include <bits/stdc++.h>
#define N 1000006
using namespace std;
typedef unsigned long long ll;
ll pri[N],num,u[N],sum[N];
bool tag[N];
void init(){
	u[1]=sum[1]=1; 
	ll a,n=1e6;
	for(int i=2;i<=n;sum[i]=sum[i-1]+u[i]*i*i,i++){
		if(!tag[i]) pri[++num]=i,u[i]=-1;
		for(int j=1;j<=num&&(a=i*pri[j])<=n;j++){
			tag[a]=1,u[a]=-u[i];
			if(i%pri[j]==0){ u[a]=0; break; }
		}
	}
}
int main(){
	init();
	ll n,sqr,res=0,now,lim_x,lim_y,z,S;
	cin>>n; sqr=sqrt(n);
	for(ll t=1,tr;t<=sqr;t=tr+1){
		tr=min((ll)sqrt(n/(n/(t*t))),sqr);
		lim_x=n/(t*t);
		for(ll x=1;x<=lim_x/(x+1);x++){
			now=(sum[tr]-sum[t-1])*x;
			lim_y=min(lim_x/x,x+x-1);
			z=n/t/t/x;
			for(ll y=x+1,yr;y<=lim_y;y=yr+1){
				yr=min(z/(z/y),lim_y);
				S=(z/y)*(z/y+1)/2;
				if((y+yr)&1) res+=(yr-y+1)/2*(y+yr)*now*S;
				else res+=(y+yr)/2*(yr-y+1)*now*S;
			}
		}
	}
	cout<<res<<endl;
}

T2

考虑答案的生成函数
F ( x ) = x F ( x ) + F ( x k ) ∑ i = 0 k − 1 x i F(x)=xF(x)+F(x^k)\sum_{i=0}^{k-1} x^i F(x)=xF(x)+F(xk)i=0k1xi
化简一下
F ( x ) = x F ( x ) + F ( x ) ( 1 1 − x − x k 1 − x ) ( 1 − x ) F ( x ) = ( 1 − x k ) F ( x k ) 1 − x F(x)=xF(x)+F(x)(\frac{1}{1-x}-\frac{x^k}{1-x})\\ (1-x)F(x)=\frac{(1-x^k)F(x^k)}{1-x} F(x)=xF(x)+F(x)(1x11xxk)(1x)F(x)=1x(1xk)F(xk)
发现两边的格式是一样的,考虑一直展开下去
F ( x ) = 1 ( 1 − x ) ∏ i ≥ 0 1 − x k i F(x)=\frac{1}{(1-x)\prod_{i\ge 0} 1-x^{k^i}} F(x)=(1x)i01xki1
然后把 1 1 − x \frac{1}{1-x} 1x1 这样展开
1 1 − x = ∑ j ≥ 0 x j = ( 1 + x + x 2 + . . . + x k − 1 ) ( 1 + x k + x 2 k + . . . x ( k − 1 ) k ) . . . 1 1 − x k i = ( 1 + x k i + x 2 k i + . . . + x ( k − 1 ) k i ) ( 1 + x k i + 1 + x 2 k i + 1 + . . . x ( k − 1 ) k i + 1 ) . . . \frac{1}{1-x}=\sum_{j\ge 0} x^j=(1+x+x^2+...+x^{k-1})(1+x^k+x^{2k}+...x^{(k-1)k})...\\ \frac{1}{1-x^{k^i}}=(1+{x^{k^{i}}}+x^{2k^{i}}+...+x^{(k-1)k^{i}})(1+x^{k^{i+1}}+x^{2k^{i+1}}+...x^{(k-1)k^{i+1}})... 1x1=j0xj=(1+x+x2+...+xk1)(1+xk+x2k+...x(k1)k)...1xki1=(1+xki+x2ki+...+x(k1)ki)(1+xki+1+x2ki+1+...x(k1)ki+1)...
代入 F ( x ) F(x) F(x) 得到
F ( x ) = ∏ i ≥ 0 ( ∑ j = 0 k − 1 x j k i ) i + 2 F(x)=\prod_{i\ge 0}(\sum_{j=0}^{k-1}x^{jk^i})^{i+2} F(x)=i0(j=0k1xjki)i+2
我们要求的答案是 [ x n ] F ( x ) [x^n]F(x) [xn]F(x) ,观察上面这个式子可以发现 ∏ i ≥ 1 ( ∑ j = 0 k − 1 x j k i ) i + 2 ≡ 0 m o d    x k \prod_{i\ge 1}(\sum_{j=0}^{k-1}x^{jk^i})^{i+2}\equiv0 \mod{x^k} i1(j=0k1xjki)i+20modxk ,所以 n m o d    k n\mod{k} nmodk 的部分是由 ( ∑ j = 0 k − 1 x j ) 2 (\sum_{j=0}^{k-1}x^j)^2 (j=0k1xj)2 中的某一项系数组成的。

题解举了个例子

在这里插入图片描述

所以每次只保留 ( ∑ j = 0 k − 1 x j ) 2 (\sum_{j=0}^{k-1}x^j)^2 (j=0k1xj)2 中次数 ≡ n   m o d   k \equiv n\ mod\ k n mod k 的项,然后对整体开 k k k 次根。然后把前面的多项式乘以后面 ∏ \prod i = 0 i=0 i=0 的部分,重复这个过程,就能得到答案。

#include <bits/stdc++.h>
#define N 502
using namespace std;
typedef long long ll;
typedef vector<ll> vec;
const int mod=1e9+7;
int n,k,a[N];
vec now,o,A;
vec mul(const vec &x,const vec &y,int lim){
	vec res; int len=x.size()+y.size()-1;
	ll tmp=0;
	for(int i=lim;i<len;i+=k){
		tmp=0;
		for(int j=max(0,i-(int)y.size()+1);j<x.size()&&j<=i;j++)
			tmp+=x[j]*y[i-j]%mod;
		res.push_back(tmp%mod);
	}
	return res;
}
void to_nxt(){
	now.resize(now.size()+k-1);
	for(int i=1;i<now.size();i++) now[i]=now[i]+now[i-1],now[i]=(now[i]<mod?now[i]:now[i]-mod);
	for(int i=now.size()-1;i>=k;i--) now[i]=now[i]-now[i-k]+mod,now[i]=(now[i]<mod?now[i]:now[i]-mod);
}
void solve(int d){
	A=mul(A,now,a[d]);
	to_nxt();
	if(d==n-1) return;
	solve(d+1);
}
int main(){
	cin>>n; 
	for(int i=0;i<n;i++) cin>>a[i];
	cin>>k;
	for(int i=0;i<k;i++) now.push_back(1);
	A.push_back(1);
	to_nxt();
	solve(0);
	cout<<A[0]<<endl;
}

T3

注意到题目保证数据随机,我们可以利用这一点来作文章。 有一个为人所熟知的结论,即设 h ( l , r ) = max ⁡ l ≤ x ≤ r a l ⊗ a x h(l, r) = \max_{l≤x≤r} a_l ⊗ a_x h(l,r)=maxlxralax,在 a a a 随机的情况下,固定左 端点 l l l 不动,所有不同的 h ( l , r ) h(l, r) h(l,r) 数量的期望为 O ( l n n ) O(ln n) O(lnn) r ∈ [ 1 , n ] r ∈ [1, n] r[1,n])。 考虑推广这一结论,我们可以大胆猜测,在 a a a 随机的情况下,固定左端点 l l l,所有不同 的 g ( l , r ) g(l, r) g(l,r) 数量的期望为 O ( l n n ) O(ln_n) O(lnn)

然后你发现你猜对了。

(想到这里后面就很自然了,不赘述了。

#include <bits/stdc++.h>
using namespace std;
namespace iobuff{
	const int LEN=1000000;
	char in[LEN+5],out[LEN+5];
	char *pin=in,*pout=out,*ed=in,*eout=out+LEN;
	inline char gc(void){
		return pin==ed&&(ed=(pin=in)+fread(in,1,LEN,stdin),ed==in)?EOF:*pin++;
	}
	inline void pc(char c){
		pout==eout&&(fwrite(out,1,LEN,stdout),pout=out);
		(*pout++)=c;
	}
	inline void flush(){fwrite(out,1,pout-out,stdout),pout=out;}
	template<typename T> inline void read(T &x){
		static int f;
		static char c;
		c=gc(),f=1,x=0;
		while(c<'0'||c>'9') f=(c=='-'?-1:1),c=gc();
		while(c>='0'&&c<='9') x=10*x+c-'0',c=gc();
		x*=f;
	}
	template<typename T> inline void putint(T x,char div){
		static char s[15];
		static int top;
		top=0;
		x<0?pc('-'),x=-x:0;
		while(x) s[top++]=x%10,x/=10;
		!top?pc('0'),0:0;
		while(top--) pc(s[top]+'0');
		pc(div);
	}
}
using namespace iobuff;
const int N=1e5+5,Q=1e6+5;
#define ll long long
int n,m,q;
namespace Trie{
	int ch[N<<5][2],sz[N<<5],mx[N<<5],inde=1;
	inline void insert(int x,int pos){
		int u=1;++sz[u];
		for(int i=m,v;~i;--i){
			v=(x>>i)&1;
			if(!ch[u][v])ch[u][v]=++inde,mx[inde]=pos;
			else mx[ch[u][v]]=pos;
			u=ch[u][v];++sz[u];
		}
	}
	int tot;
	inline void query(int u,int L,int x,int dep,int *ans){
		if(!u||!sz[u]||mx[u]<L)return;
		if(dep<0){ans[++tot]=mx[u];return;}
		int v=x>>dep&1,l=ch[u][v],r=ch[u][v^1];
		if(!l||!r){query(l^r,L,x,dep-1,ans);return;}
		if(mx[r]>mx[l]){query(r,L,x,dep-1,ans);return;}
		else{
			query(l,max(L,mx[r]),x,dep-1,ans);
			if(L<mx[r])query(r,L,x,dep-1,ans);
		}
	}
}
namespace BIT{
	ll t1[N],t2[N];
	void modify(int l,int r,ll v){
		if(l>r)return;
		for(int x=l;x<=n;x+=(x&-x)) t1[x]+=v,t2[x]+=v*l;
		for(int x=r+1;x<=n;x+=(x&-x)) t1[x]-=v,t2[x]-=v*(r+1);
	}
	ll query(int x){
		ll ret=0;
		for(int i=x;i;i-=(i&-i)) ret+=t1[i]*(x+1)-t2[i];
		return ret;
	}
}
int pos[N],val[N],tot,mxpos[N],mxval[N],mxtot,buc1[N],buc2[N],curtot;
ll sum;
inline void merge(){
	curtot=0;
	int j=1;
	for(int i=1;i<=mxtot;++i){
		while(j<=tot&&pos[j]>=mxpos[i]){
			buc1[++curtot]=pos[j];
			buc2[curtot]=val[j++];
		}
		buc1[++curtot]=mxpos[i];
		buc2[curtot]=mxval[i];
	}
	while(j<=tot){
		buc1[++curtot]=pos[j];
		buc2[curtot]=val[j++];
	}
	mxtot=0;
	for(int i=1;i<=curtot;++i){
		if(buc2[i]<=mxval[mxtot])continue;
		if(mxpos[mxtot]==buc1[i])--mxtot;
		mxval[++mxtot]=buc2[i];
		mxpos[mxtot]=buc1[i];
	}
	mxpos[mxtot+1]=0;
	for(int i=1;i<=mxtot;++i){
		sum+=1ll*mxval[i]*(mxpos[i]-mxpos[i+1]);
		BIT::modify(mxpos[i+1]+1,mxpos[i],mxval[i]);
	}
}
int x[N],tp;
struct Query{int l,r,id;}query[Q];
inline bool operator <(Query a1,Query a2){return a1.r<a2.r;}
ll ans[Q];

inline void read(int n,int m,unsigned int seed,int tp){
	mt19937 rnd(seed);
	for(int i=1;i<=n;++i){
		if(tp==4) x[i]=1<<(rnd()%m);
		else x[i]=rnd()&((1<<m)-1);
	}
}
unsigned int seed;

int main(){
	read(n);read(m);read(q);read(tp);
	read(seed);
	read(n,m,seed,tp);--m;
	for(int i=1;i<=q;++i){read(query[i].l);read(query[i].r);query[i].id=i;}
	sort(query+1,query+1+q);
	int flag=1;ll ret=0;
	tp=(q>=100000);
	for(int i=1;i<=n&&flag<=q;++i){
		Trie::tot=0;
		Trie::query(1,0,x[i],m,pos);
		tot=Trie::tot;
		for(int j=1;j<=tot;++j)val[j]=x[i]^x[pos[j]];
		Trie::insert(x[i],i);
		merge();
		while(flag<=q&&query[flag].r==i){
			ans[query[flag].id]=sum-BIT::query(query[flag].l-1);
			ans[query[flag].id]=sum-BIT::query(query[flag].l-1);
			if(tp)ret^=ans[query[flag].id];++flag;
		}
	}
	if(tp){
		putint(ret,'\n');flush();return 0;
	}
	for(int i=1;i<=q;++i)putint(ans[i],'\n');flush();
	return 0;
}
posted @ 2022-10-10 20:18  缙云山车神  阅读(19)  评论(0编辑  收藏  举报