ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2021.11.1考试总结[冲刺NOIP模拟20]

2021-11-01 16:03:48  阅读:108  来源: 互联网

标签:ch 20 NN NOIP int namespace long frac 2021.11


今天好像全是简单题,但仍然没想到多少正解,考完一个半小时就改完了。。

对各种知识点还是没有理解透,一些套路想不出来

\(\Huge{\color{green}{菜}}\)

T1 集合均值

列出贡献发现每个元素贡献的概率为

\[\frac{1}{n\times m}\sum_{i=1}^{n\times m} \frac{i}{i+1} \]

那么答案为

\[(m\times\sum_{i=1}^nw_i)\times\frac{1}{n\times m}\sum_{i=1}^{n\times m} \frac{i}{i+1} \]

线性求逆元

\[inv_i\equiv \left\lfloor \frac{p}{i}\right\rfloor\times inv_{p\;mod\;i} (mod\;p) \]

或直接线性筛逆元。

\(code:\)

T1
#include<bits/stdc++.h>
#define int long long
using namespace std;

namespace IO{
	typedef long long LL;
	int read(){
		LL x=0,f=1; char ch=getchar();
		while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
		while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
		return x*f;
	}
	void write(LL x,char sp){
		char ch[20]; int len=0;
		if(x<0) x=-x,putchar('-');
		do{ ch[len++]=x%10+'0'; x/=10; }while(x);
		for(int i=len-1;~i;i--) putchar(ch[i]); putchar(sp);
	}
	void ckmin(int& x,int y){ x=x<y?x:y; }
	void ckmax(LL& x,LL y){ x=x>y?x:y; }
} using namespace IO;

const int NN=20000010,mod=998244353;
int n,m,tot,sum,base;
int cnt,pri[NN],inv[NN];
bool vis[NN];
int qpow(int a,int b){
	int res=1;
	for(;b;b>>=1){
		if(b&1) res=res*a%mod;
		a=a*a%mod;
	}
	return res;
}
void getinv(){
	inv[0]=inv[1]=1;
	for(int i=2;i<=tot+1;i++){
		if(!vis[i]) pri[++cnt]=i,inv[i]=qpow(i,mod-2);
		for(int j=1;j<=cnt&&pri[j]*i<=tot;j++){
			vis[pri[j]*i]=1;
			inv[pri[j]*i]=inv[i]*inv[pri[j]]%mod;
			if(i%pri[j]==0) break;
		}
	}
}

signed main(){
	freopen("mos.in","r",stdin);
	freopen("mos.out","w",stdout);
	n=read(); m=read(); tot=n*m;
	getinv();
	for(int i=1;i<=n;i++) sum+=read();
	sum=sum%mod*m%mod;
	for(int i=1;i<=tot;i++)
		(base+=i*inv[i+1])%=mod;
	sum=sum*inv[tot]%mod;
	sum=sum*base%mod;
	write(sum,'\n');
	return 0;
}

T2 聚烷撑乙二醇

期望要逆推。然后没了

对于一个生成器,若它生成的数小于它之后的期望,那么不取它,否则取它。

最后一个生成器期望为\(\frac{l_i+r_i}{2}\),第一个生成器的期望为答案。

\(code:\)

T2
#include<bits/stdc++.h>
using namespace std;

namespace IO{
	typedef long long LL;
	typedef long double DB;
	int read(){
		LL x=0,f=1; char ch=getchar();
		while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
		while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
		return x*f;
	}
	void write(LL x,char sp){
		char ch[20]; int len=0;
		if(x<0) x=-x,putchar('-');
		do{ ch[len++]=x%10+'0'; x/=10; }while(x);
		for(int i=len-1;~i;i--) putchar(ch[i]); putchar(sp);
	}
	void ckmin(int& x,int y){ x=x<y?x:y; }
	void ckmax(LL& x,LL y){ x=x>y?x:y; }
} using namespace IO;

const int NN=1000010;
int n;
DB f[NN],l[NN],r[NN];

signed main(){
	freopen("pag.in","r",stdin);
	freopen("pag.out","w",stdout);
	n=read();
	for(int i=1;i<=n;i++)
		l[i]=read(),r[i]=read();
	f[n]=(l[n]+r[n])/2;
	for(int i=n-1;i;i--){
		if(f[i+1]<=l[i]){ f[i]=(l[i]+r[i])/2.0; continue; }
		else if(f[i+1]>=r[i]){ f[i]=f[i+1]; continue; }
		f[i]=(f[i+1]-l[i])*f[i+1]/(r[i]-l[i])+(r[i]-f[i+1])*(f[i+1]+r[i])/2.0/(r[i]-l[i]);
	}
	printf("%.5Lf\n",f[1]);
	return 0;
}

T3 技术情报局

暴力考利枚举每个值,单调栈算出它成为最大值的区间,然后可以线段树求区间的子区间乘积和,具体维护区间元素乘积,前缀乘积和,后缀成积和与子区间乘积和,转移略。

正解在笛卡尔树上合并信息,可以去\(log\)。也可以在单调栈时直接合并,避免爆栈。

\(code:\)

T3
#include<bits/stdc++.h>
#define int long long
using namespace std;

namespace IO{
	typedef long long LL;
	int read(){
		LL x=0,f=1; char ch=getchar();
		while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
		while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
		return x*f;
	}
	void write(LL x,char sp){
		char ch[20]; int len=0;
		if(x<0) x=-x,putchar('-');
		do{ ch[len++]=x%10+'0'; x/=10; }while(x);
		for(signed i=len-1;~i;i--) putchar(ch[i]); putchar(sp);
	}
	void ckmin(int& x,int y){ x=x<y?x:y; }
	void ckmax(LL& x,LL y){ x=x>y?x:y; }
} using namespace IO;

const int NN=10000010;
int n,L,R,ans,mod;
unsigned s;
vector<int>v;

namespace GenHelper{
	unsigned z1, z2, z3, z4, b;
	unsigned rand_(){
		b=((z1<<6)^z1)>>13;
		z1=((z1&4294967294U)<<18)^b;
		b=((z2<<2)^z2)>>27;
		z2=((z2&4294967288U)<<2)^b;
		b=((z3<<13)^z3)>>21;
		z3=((z3&4294967280U)<<7)^b;
		b=((z4<<3)^z4)>>12;
		z4=((z4&4294967168U)<<13)^b;
		return (z1^z2^z3^z4);
	}
	vector<int>get(int n,unsigned s,int l,int r){
		vector<int>a; a.push_back(0);
		z1=s;
		z2=unsigned((~s)^0x233333333U);
		z3=unsigned(s^0x1234598766U);
		z4=(~s)+51;
		for(signed i=1;i<=n;i++){
			int x=rand_()&32767;
			int y=rand_()&32767;
			a.push_back(l+(x*32768+y)%(r-l+1));
		}
		return a;
	}
}
namespace Cartesion_Tree{
	int top,root,ls[NN],rs[NN],stk[NN];
	struct node{
		int sum,lll,rrr,mul;
		node(){}
		node(int a,int b,int c,int d){
			sum=a; lll=b; rrr=c; mul=d;
		}
		node operator+(const node& rr)const{
			node res;
			res.sum=(sum+rr.sum+rrr*rr.lll)%mod;
			res.lll=(lll+mul*rr.lll)%mod;
			res.rrr=(rr.rrr+rrr*rr.mul)%mod;
			res.mul=mul*rr.mul%mod;
			return res;
		}
	}f[NN<<2];
	void build(){
		for(int k,i=1;i<=n;i++){
			k=top;
			while(k&&v[stk[k]]<v[i]) --k;
			if(!k) root=i;
			else rs[stk[k]]=i;
			if(k<top) ls[i]=stk[k+1];
			stk[++(top=k)]=i;
		}
	}
	void dfs(int u){
		f[u]=node(v[u],v[u],v[u],v[u]);
		if(ls[u]) dfs(ls[u]), f[u]=f[ls[u]]+f[u];
		if(rs[u]) dfs(rs[u]), f[u]=f[u]+f[rs[u]];
		(ans+=v[u]*(mod+mod+f[u].sum-f[ls[u]].sum-f[rs[u]].sum))%=mod;
	}
} using namespace Cartesion_Tree;

signed main(){
	freopen("tio.in","r",stdin);
	freopen("tio.out","w",stdout);
	n=read(); s=read(); L=read(); R=read(); mod=read();
	v=GenHelper::get(n,s,L,R);
	build(); dfs(root);
	write(ans,'\n');
	return 0;
}

T4 肯德基

就是要求没有平方因子数的和。(也许是套路?

枚举平方因子,根据它的质因子个数进行容斥,发现容斥系数就是莫比乌斯函数。易得

\[ans=\sum_{i=1}^{\sqrt n}\mu(i)i^2\sum_{j=1}^{\left\lfloor \frac{n}{i^2}\right\rfloor}j \]

\(i=1\)时为总方案,之后按质因子个数进行容斥。

对\(\left\lfloor\frac{n}{i^2}\right\rfloor\)整除分块,每次\(r^2\)为\(\left\lfloor \frac{n}{\left\lfloor n/l^2\right\rfloor}\right\rfloor\),因此\(r\)应取\(\sqrt{\left\lfloor \frac{n}{\left\lfloor n/l^2\right\rfloor}\right\rfloor}\),可以证明单次询问复杂度是\(O(\sqrt[3]{n})\)的(然而我不会

\(code:\)

T4
#include<bits/stdc++.h>
#define int unsigned long long
using namespace std;

namespace IO{
	typedef long long LL;
	int read(){
		int x=0,f=1; char ch=getchar();
		while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
		while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
		return x*f;
	}
	void write(int x,char sp){
		char ch[20]; int len=0;
		if(x<0) x=-x,putchar('-');
		do{ ch[len++]=x%10+'0'; x/=10; }while(x);
		for(int i=len-1;~i;i--) putchar(ch[i]); putchar(sp);
	}
	void ckmin(int& x,int y){ x=x<y?x:y; }
	void ckmax(LL& x,LL y){ x=x>y?x:y; }
} using namespace IO;

const int NN=10000010;
int t,n,mu[NN],pre[NN];
signed cnt,pri[NN];
bool vis[NN];
int S(int x){ return (x&1)?(x+1)/2*x:x/2*(x+1); }
void prprprprprprprpr(){
	mu[1]=1;
	for(int i=2;i<=1e7;i++){
		if(!vis[i]) pri[++cnt]=i,mu[i]=-1;
		for(int j=1;j<=cnt&&pri[j]*i<=1e7;j++){
			vis[pri[j]*i]=1;
			if(i%pri[j]==0){ mu[pri[j]*i]=0; break; }
			mu[pri[j]*i]=-mu[i];
		}
	}
	for(int i=1;i<=1e7;i++)
		pre[i]=pre[i-1]+mu[i]*i*i;
}
int ans(){
	int l=1,r,ext=sqrt(n),res=0;
	while(l<=ext){
		r=sqrt(n/(n/l/l));
		res+=S(n/l/l)*(pre[r]-pre[l-1]);
		l=r+1;
	}
	return res;
}

signed main(){
	freopen("kfc.in","r",stdin);
	freopen("kfc.out","w",stdout);
	t=read();
	prprprprprprprpr();
	while(t--){
		n=read();
		write(ans(),'\n');
	}
	return 0;
}

标签:ch,20,NN,NOIP,int,namespace,long,frac,2021.11
来源: https://www.cnblogs.com/keeeeeeen/p/15494134.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有