ICode9

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

NOIP2022模拟赛二 By yzxoi 8.17

2022-08-17 17:01:28  阅读:100  来源: 互联网

标签:le frac yzxoi int cdot beta NOIP2022 8.17 now


Preface

今天早上被公交车搞了,晚了30min才到……

最后T1读入\(n\)的时候写%d了,喜提30pts(结果Rank竟然不变233)


A. 「NOIP2022模拟赛二 By yzxoi A」『Pale』/ feat. 初音ミク

Pro

  • 有线性递推数列\(F\)满足:

    \[F(n)=3F(n-1)+2F(n-2)(n\ge 2)\\ F(0)=0,F(1)=1 \]

  • \(Q\)次询问,每次询问\(F(n)\mod 998244353\),强制在线

  • \(Q\le 10^7,n\le 10^{18}\)

Sol

以前学OI的时候推不来这种东西,现在参加完高考后发现还没平时做的题难……

首先构造等比数列求解,先待定个系数\(\alpha.\beta\),有:

\[f(n)+\beta\cdot f(n-1)=\alpha\cdot (f(n)+\beta\cdot f(n-1))(n\ge 2)\\ \Leftrightarrow f(n)=(\alpha -\beta)\cdot f(n-1)+\alpha\beta\cdot f(n-2)(n\ge 2) \]

由递推式解得:

\[\begin{cases}\alpha_1=\frac{3+\sqrt{17}}{2}\\\beta_1=\frac{\sqrt{17}-3}{2}\end{cases},\begin{cases}\alpha_2=\frac{3-\sqrt{17}}{2}\\\beta_2=-\frac{3+\sqrt{17}}{2}\end{cases} \]

得到:

\[\begin{cases}f(n)+\beta_1\cdot f(n-1)=\alpha_1^{n-1}\cdot(f(1)+\beta_1\cdot f(0))\\f(n)+\beta_2\cdot f(n-1)=\alpha_2^{n-1}\cdot(f(1)+\beta_2\cdot f(0))\end{cases} \]

联立消去\(f(n-1)\)得到\(f(n)=\frac{\alpha_2^n\beta_1-\alpha_1^n\beta _2}{\beta_1-\beta_2}=\frac{(\frac{3+\sqrt{17}}{2})^n-(\frac{3-\sqrt{17}}{2})^n}{\sqrt {17}}\)

然后由于数据范围很大我们需要\(O(1)\)快速幂,直接根号分治一下即可

#include<cstdio>
#define RI register int
#define CI const int&
#define CL const long long&
using namespace std;
const int mod=998244353,S=100000,sqrt_17=473844410;
int q,a1[S+5],ap1[S],a2[S+5],ap2[S],inv,cur,ans; long long n;
inline int quick_pow(int x,int p=mod-2,int mul=1)
{
	for (;p;p>>=1,x=1LL*x*x%mod) if (p&1) mul=1LL*mul*x%mod; return mul;
}
inline int QP(int *A,int *B,int p)
{
	return 1LL*A[p%S]*B[p/S]%mod;
}
inline int sub(CI x,CI y)
{
	return x-y<0?x-y+mod:x-y;
}
inline int F(CL n)
{
	return 1LL*sub(QP(a1,ap1,n%(mod-1)),QP(a2,ap2,n%(mod-1)))*inv%mod;
}
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	RI i; scanf("%d%lld",&q,&n); inv=quick_pow(sqrt_17); a1[0]=a2[0]=ap1[0]=ap2[0]=1;
	a1[1]=1LL*(3+sqrt_17)*quick_pow(2)%mod; a2[1]=1LL*(3-sqrt_17+mod)*quick_pow(2)%mod;
	for (i=2;i<=S;++i) a1[i]=1LL*a1[i-1]*a1[1]%mod,a2[i]=1LL*a2[i-1]*a2[1]%mod;
	for (i=1;i<S;++i) ap1[i]=1LL*ap1[i-1]*a1[S]%mod,ap2[i]=1LL*ap2[i-1]*a2[S]%mod;
	for (ans=cur=F(n),i=2;i<=q;++i) n=n^(1LL*cur*cur),cur=F(n),ans^=cur;
	return printf("%d",ans),0;
}

B. 「NOIP模拟赛二 By yzxoi B」Oval and Function

Pro

  • 求不定方程\(x^2+3y^2=N^2\)的整数解的个数
  • 数据组数\(T\le 10\),\(n\le 10^{12}\)

Sol

刚开始写了个假算法求助陈指导被点破后发现这题两年前校内模拟赛做过,但我已经完全没有印象了的说

先讲一个假算法,刚开始考虑到利用平方换元法(也是高考中常用方法233),得到:

\[\begin{cases}x=k\cdot(m^2-3n^2)\\y=k\cdot(2mn)\\N=k\cdot(m^2+3n^2) \end{cases} \]

其中\(k,m,n\)均为整数,只要枚举\(k|N\)然后再枚举\(n\)即可

但是这样并不能表示所有的情况,因为\(y\)显然只能是偶数

考虑正解,首先由于\(x=\pm n,y=0\)是显然成立的两组通解,而\(x=0\)时显然无解

并且若\((x,y),x,y\in N^*\)为一组解,那么\((x,-y),(-x,y),(-x,-y)\)也都是解

因此我们可以强制\(x,y\in N^*\),最后把答案乘\(4\)再加\(2\)即可

考虑令\(a=N-x\),则:

\[(N-a)^2+3y^2=N^2\Leftrightarrow -2Na+a^2+3y^2=0\Leftrightarrow 3y^2={a\cdot(2N-a)} \]

设\(d=\gcd(a,2N-a)=\gcd(a,2N)\),在上面的式子两边同时除以\(d^2\)得到

\[3(\frac{y}{d})^2=\frac{a}{d}\cdot \frac{2N-a}{d},(\gcd(\frac{a}{d},\frac{2N-a}{d})=1) \]

互质的两数相乘是一个平方数的\(3\)倍,则这两个数必然一个是平方数,一个是某平方数的\(3\)倍

因此设\(\frac{a}{d}=3i^2,\frac{2N-a}{d}=j^2(i,j\in N^*,\gcd(3i,j)=1)\)(反之亦然),于是:

\[\frac ad+\frac{2N-a}d=3i^2+j^2\Leftrightarrow \frac{2N}d=3i^2+j^2 \]

因此直接枚举\(d|2N\),然后枚举\(i\)即可,复杂度上界是\(O(T\cdot n^{\frac{3}{4}})\),显然跑不满

#include<cstdio>
#include<cmath>
#define RI register int
#define CI const int&
#define int long long
using namespace std;
int t,n;
inline int gcd(CI n,CI m)
{
	return m?gcd(m,n%m):n;
}
inline int calc(CI x,int ret=0)
{
	for (RI i=1;3LL*i*i<=x;++i)
	{
		int y=sqrt(x-3LL*i*i); if (y*y!=x-3LL*i*i) continue;
		if (gcd(3LL*i,y)==1) ++ret;
	}
	return ret;
}
signed main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	for (scanf("%lld",&t);t;--t)
	{
		int ans=0; scanf("%lld",&n); n<<=1; for (RI i=1;i*i<=n;++i)
		if (n%i==0) if (ans+=calc(n/i),i*i!=n) ans+=calc(i);
		printf("%lld\n",(ans<<2LL)+2);
	}
	return 0;
}

C. 「NOIP2022模拟赛二 By yzxoi C」『 だきしめるまで。』/ feat. 可不

Pro

  • 给定一个\(n\)个点,\(m\)条边的有向图,\(q\)次询问从\(s\)到\(t\)经过至少\(k\)条边的最短路
  • 数据组数\(T\le 10,2\le n\le 50,1\le m,k\le 10^4,1\le q\le 10^5\)

Sol

首先不难想到一个暴力做法,设\(f_{t,i,j}\)表示从\(i\)恰好经过\(t\)条边到\(j\)的最短路

但这样做因为\(k\le 10000\)显然是会爆炸的,考虑拆分问题

而这种拆分的方法一般就两种:倍增根号分治,这道题显然不好倍增,因此考虑根号分治

设\(a_{t,i,j}\)表示从\(i\)至少经过\(t\)条边到\(j\)的最短路,\(pa_{t,i,j}\)表示\(i\)恰好经过\(100t\)条边到\(j\)的最短路

每次询问\(s\to t\)时考虑枚举一个中间点\(i\),设\(p=k\operatorname{mod} 100,q=\lfloor\frac{k}{100}\rfloor\),则答案就是

\[\min_\limits{1\le i\le n} (pa_{q,s,i}+a_{p,i,t}) \]

复杂度\(O(100n^3+qn)\)

#include<cstdio>
#include<iostream>
#define RI register int
#define CI const int&
#define CL const long long&
using namespace std;
const int N=55,S=105,INF=1e9;
int T,n,m,q,x,y,z,c[N][N],d[N][N],a[S][N][N],pa[S][N][N],tmp[N][N];
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	for (scanf("%d",&T);T;--T)
	{
		RI i,j,k,t; for (scanf("%d%d",&n,&m),i=1;i<=n;++i) for (j=1;j<=n;++j)
		c[i][j]=INF,a[0][i][j]=pa[0][i][j]=(i==j?0:INF);
		for (i=1;i<=m;++i) scanf("%d%d%d",&x,&y,&z),c[x][y]=min(c[x][y],z);
		for (t=1;t<=100;++t) for (i=1;i<=n;++i) for (j=1;j<=n;++j) 
		for (a[t][i][j]=INF,k=1;k<=n;++k) a[t][i][j]=min(a[t][i][j],a[t-1][i][k]+c[k][j]);
		for (t=1;t<=100;++t) for (i=1;i<=n;++i) for (j=1;j<=n;++j)
		for (pa[t][i][j]=INF,k=1;k<=n;++k) pa[t][i][j]=min(pa[t][i][j],pa[t-1][i][k]+a[100][k][j]);
		for (i=1;i<=n;++i) for (j=1;j<=n;++j) d[i][j]=(i==j?0:c[i][j]);
		for (k=1;k<=n;++k) for (i=1;i<=n;++i) for (j=1;j<=n;++j)
		d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
		for (t=0;t<=100;++t)
		{
			for (i=1;i<=n;++i) for (j=1;j<=n;++j) tmp[i][j]=INF;
			for (i=1;i<=n;++i) for (j=1;j<=n;++j) for (k=1;k<=n;++k)
			tmp[i][j]=min(tmp[i][j],pa[t][i][k]+d[k][j]);
			for (i=1;i<=n;++i) for (j=1;j<=n;++j) pa[t][i][j]=tmp[i][j];
		}
		for (scanf("%d",&q);q;--q)
		{
			scanf("%d%d%d",&x,&y,&z); int p=z%100,q=z/100,ans=INF;
			for (i=1;i<=n;++i) ans=min(ans,a[p][x][i]+pa[q][i][y]);
			printf("%d\n",ans!=INF?ans:-1);
		}
	}
	return 0;
}

D. 「NOIP2022模拟赛二 By yzxoi D」『くうになる』 / feat. 初音ミク & 可不

Pro

  • 给定长度为\(n\)的序列\(A\),求:

    \[\sum_{1\leq i < j\leq n}\max\{A_i,A_{i+1},\cdots,A_j\} [(A_i\&A_j)=A_j \lor (A_i\& A_j)=A_i] \]

  • \(n\le 10^5,0\le A_i\le 10^{14}\)

Sol

#include<cstdio>
#define RI register int
#define CI const int&
using namespace std;
const int N=10000005;
int n,a[N],rt; long long ans;
class Cartesian_tree
{
	private:
		struct CT
		{
			int ch[2],sz;
		}node[N]; int stk[N],top,val,f[1<<15],g[1<<15],h[1<<15];
		#define lc(x) node[x].ch[0]
		#define rc(x) node[x].ch[1]
		#define ch(x,y) node[x].ch[y]
		#define sz(x) node[x].sz
		inline void add(CI x,CI y)
		{
			int A=x>>7<<7,B=x&127; h[x]+=y; for (RI i=0;i<128;++i)
			{
				if ((B&i)==B) f[A|i]+=y; if ((B&i)==i) g[A|i]+=y;
			}
		}
		inline void ask(CI x)
		{
			int A=x>>7,B=x&127; ans-=1LL*val*h[x]; for (RI i=0;i<=128;++i)
			{
				if ((A&i)==i) ans+=1LL*val*f[(i<<7)|B];
				if ((A&i)==A) ans+=1LL*val*g[(i<<7)|B];
			}
		}
		inline void modify(CI now,CI v)
		{
			add(a[now],v); if (lc(now)) modify(lc(now),v); if (rc(now)) modify(rc(now),v);
		}
		inline void query(CI now)
		{
			ask(a[now]); if (lc(now)) query(lc(now)); if (rc(now)) query(rc(now));
		}
	public:
		inline void build(void)
		{
			for (RI i=1;i<=n;++i)
			{
				while (top&&a[i]>a[stk[top]]) --top;
				if (top) lc(i)=rc(stk[top]),rc(stk[top])=i;
				else lc(i)=stk[top+1]; stk[++top]=i;
			}
			rt=stk[1];
		}
		inline void getsz(CI now=rt)
		{
			if (sz(now)=1,lc(now)) getsz(lc(now)),sz(now)+=sz(lc(now)); if (rc(now)) getsz(rc(now)),sz(now)+=sz(rc(now));
		}
		inline void DSU(CI now=rt)
		{
			int d=sz(lc(now))<sz(rc(now));if (ch(now,d^1)) DSU(ch(now,d^1)),modify(ch(now,d^1),-1);
			if (ch(now,d)) DSU(ch(now,d)); add(a[now],1); val=a[now]; ask(a[now]);
			if (ch(now,d^1)) query(ch(now,d^1)),modify(ch(now,d^1),1);
		}
		#undef lc
		#undef rc
		#undef ch
		#undef sz
}T;
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	RI i; for (scanf("%d",&n),i=1;i<=n;++i) scanf("%d",&a[i]),ans-=a[i];
	return T.build(),T.getsz(),T.DSU(),printf("%lld",ans),0;
	
}

标签:le,frac,yzxoi,int,cdot,beta,NOIP2022,8.17,now
来源: https://www.cnblogs.com/cjjsb/p/16595855.html

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

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

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

ICode9版权所有