首页 > 其他分享 >2023.8.16模拟赛总结

2023.8.16模拟赛总结

时间:2023-08-16 22:34:10浏览次数:35  
标签:return 16 int LL ret fpow freopen 2023.8 模拟

T1 Idiot 的乘幂

题目大意就是给\(a,b,c,d,p\)满足

求解

这题考场一开始发现\(\gcd(a,c)=1\)没啥用,后来发现其实很巧妙,直接辗转相除\(a,c\)同时维护\(\chi^a,\chi^c\)最后剩下来的就是\(\chi\)

当然题解给了一个鬼才想到的做法构造\(\chi =\chi^1=\chi^{ax+cy}\)

所以可以用exgcd求解方程

\[ax+cy=1 \]

然后直接用\(\chi=b^xd^y\)求解就行了。

#include<bits/stdc++.h>
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
using namespace std;
typedef long long LL;
LL fpow(LL a,LL b,LL P){LL ret=1; 
	for(;b;b>>=1,a=a*a%P)
	if(b&1)ret=ret*a%P;
	return ret;
}
LL exgcd(LL a,LL b,LL &x,LL &y){
	if(b==0)return x=1,y=0,a;
	LL d=exgcd(b,a%b,y,x);
	return y=y-a/b*x,d;
}
LL inv(LL x,LL P){
	LL ret,kth;
	exgcd(x,P,ret,kth);
	return (ret%P+P)%P;
}
LL solve(LL a,LL b,LL ib,LL c,LL d,LL id,LL P){
	if(c==0)return b;
	return solve(c,d,id,a%c,b*fpow(id,a/c,P)%P,ib*fpow(d,a/c,P)%P,P); 
}
int main(){
	int T;scanf("%lld",&T);
	while(T--){
		LL a,b,c,d,P;
		scanf("%lld%lld%lld%lld%lld",&a,&b,&c,&d,&P);
		if(fpow(b,c,P)!=fpow(d,a,P)){
		puts("No Solution!");continue;}
		LL ans=solve(a,b,inv(b,P),c,d,inv(d,P),P);
		if(fpow(ans,a,P)==b&&fpow(ans,c,P)==d)
		printf("%lld\n",ans);
		else puts("No Solution!");
	}
	return 0;
}

T2 小 D 与原题

大意说构造\(n-1\)组,每组\(\frac n 2\)个点对,使得每组里用的数不同,\(n-1\)组里使用的所有点对不相同

这个题一眼淼题,再看一眼就会爆炸发现不简单,他要求每次\(\frac n2\)题使用的原题不能相同,当然在一小时思考后想出了正解。

考虑把点从\(0\)到\(n-1\)标号,我们使第\(x+1\)组匹配包含满足\(i+j\equiv x(\mod n-1)\)的边\((i,j)\)和一条边\((p,n-1)\)满足\(2p\equiv x(\mod n-1)\)就可以了,正确性可以保证

#include<bits/stdc++.h>
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
using namespace std;
const int N=1005;
int n;
bool flag[N][N];
int main(){
	scanf("%d",&n);
	for(int i=1;i<n;i++,putchar(10))
	for(int j=1;j<n;j++){
		int k=(n-1-j+i)%(n-1)+1;
		if(k==j)k=n;
		if(j!=k&&!flag[j][k]){
			printf("%d %d ",j,k);
			flag[j][k]=flag[k][j]=1;
		}
	}
	return 0;
}

T3 小 D 与随机

大意说给一棵树,定义好点为一个点权值是这个点到根的链上所有节点权值的最大值,每个节点的权值为1到n,且两两不同,好点个数为\(c\),求\(k^c\)的总和

考场,考虑水分,观察到有\(40\%\)的链,直接dp,这里很滑稽,20分暴力不会写写了个40分的链。

设状态\(f_i\)表示前\(i\)个答案的总和,因为如果第\(i\)个点是好点那么对于前\(i\)个节点来说它只有一种选法,如果\(i\)个点不是好点的话它不能选最大的所以有\(i-1\)种选法,可得转移

\[f_i=kf_{i-1}+(i-1)f_{i-1} \]

那么现在考虑正解,我们把树上的好点染成黑点,其他为白点

设\(f_{i,j}\)为以\(i\)为根的子树中有\(j\)个黑点的期望,先用树形背包转移出在\(i\)子树中不计\(i\)节点的\(f\)值。

然后分类讨论

  • 若\(i\)节点为黑点那么,显然的概率为\(\frac 1{j+1}\)有转移\(F_j=F_j+\frac{kf_{i,j}}{j+1}\)
  • 若\(i\)节点为白点,我们可以容斥一波,先加上当前点随便黑白的期望,再减去当前节点为黑点的期望,发现\(F_j=F_j+f_{i,j}-f_{i,j-1}\)

综合一下转移即可

#include<bits/stdc++.h>
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
using namespace std;
typedef long long LL;
const int N=5005;
const LL mod=998244353;
LL fac[N+5],inv[N+5];
LL fpow(LL a,LL b){LL ret=1;
	for(;b;b>>=1,a=a*a%mod)
	if(b&1)ret=ret*a%mod;
	return ret;
}
void init(){fac[0]=1;
	for(int i=1;i<=N;i++)fac[i]=fac[i-1]*i%mod;
	inv[N]=fpow(fac[N],mod-2);
	for(int i=N;i;i--)inv[i-1]=inv[i]*i%mod;
}
LL Inv(LL x){return inv[x]*fac[x-1]%mod;}

struct Edge{int Nxt,To;}Ed[N<<1];
int Head[N],Cnt;
void Add(int u,int v){
	Ed[++Cnt]={Head[u],v};
	Head[u]=Cnt;
}

LL f[N][N],F[N],K;
int sze[N];
void add(LL &x,LL y){x=(x+y+mod)%mod;}
void Dfs(int u,int fa){
	f[u][0]=1;
	for(int i=Head[u],v;i;i=Ed[i].Nxt)
	if((v=Ed[i].To)!=fa){
		Dfs(v,u);
		for(int j=0;j<=sze[u];j++)
		for(int k=0;k<=sze[v];k++)
		add(F[j+k],f[u][j]*f[v][k]%mod);
		sze[u]+=sze[v];
		for(int j=0;j<=sze[u];j++)
		f[u][j]=F[j],F[j]=0;
	}
	for(int i=0;i<=sze[u];i++){
		add(F[i+1],f[u][i]*K%mod*Inv(i+1)%mod);
		if(fa)add(F[i],f[u][i]),add(F[i+1],-f[u][i]);
	}
	sze[u]++;
	for(int i=0;i<=sze[u];i++)f[u][i]=F[i],F[i]=0;
}
int main(){
	init();
	int n;
	scanf("%d%lld",&n,&K);
	for(int i=1,u,v;i<n;i++)
	scanf("%d%d",&u,&v),Add(u,v),Add(v,u); 
	Dfs(1,0);
	LL ans=0;
	for(int i=1;i<=n;i++)add(ans,f[1][i]);
	printf("%lld",ans*fac[n]%mod);
	return 0;
}

T4 小 D 与游戏

这题考场没交,没啥想法。

题目大意是说一个由a,b,c组成的字符串,每次可以选两个相邻且不同的字符,把这两个字符改成另外一个字符

直接上正解,该题有以下结论

  • 首先考虑把a,b,c分别设为0,1,2,那么会发现每次修改,字符串的每位之和前后是相同的
  • 然后是最终串必然至少有两个相邻的相同字符(除非初始串相邻两两不同然后不操作)
  • 最后是只要满足以上两条的字符串都可以构造出来(最为离谱,不会证)

这题的三个结论对于\(|S|\le 3\)不适用,所以可以打表

最后特判一下初始相邻两两不同的情况,答案++,和字符全相同直接输出1即可

#include<bits/stdc++.h>
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
using namespace std;
typedef long long LL;
const int N=2e5+5;
const LL mod=998244353;
char ch[N];
int a[N];
LL f[N][3][3][2];
LL add(LL &x,LL y){x+=y,x%=mod;}
int main(){fre(game);
	cin>>ch+1;
	int n=strlen(ch+1),m=0;
	for(int i=1;i<=n;i++)
	a[i]=ch[i]-'a',m+=a[i],m%=3;
	if(n==1)return puts("1"),0;
	if(n==2)return puts(a[1]==a[2]?"1":"2"),0;
	if(n==3){
		if(a[1]==a[2]&&a[2]==a[3])puts("1");
		else if(a[1]==a[2]||a[2]==a[3])puts("6");
		else if(a[1]==a[3])puts("7");
		else puts("3");
		return 0;
	}
	f[1][0][0][0]=f[1][1][1][0]=f[1][2][2][0]=1;
	for(int i=2;i<=n;i++)
	for(int j=0;j<=2;j++)
	for(int k=0;k<=2;k++)
	for(int w=0;w<=2;w++){
		if(j!=k||i==1)
		add(f[i][j][(w+j)%3][1],f[i-1][k][w][1]),
		add(f[i][j][(w+j)%3][0],f[i-1][k][w][0]);
		else 
		add(f[i][j][(w+j)%3][1],f[i-1][k][w][1]),
		add(f[i][j][(w+j)%3][1],f[i-1][k][w][0]);
	}
	LL ans=0;bool flag1=1,flag2=1;
	for(int i=1;i<n;i++)if(a[i]!=a[i+1]){flag1=0;break;}
	for(int i=1;i<n;i++)if(a[i]==a[i+1]){flag2=0;break;}
	for(int i=0;i<=2;i++)ans=(ans+f[n][i][m][1])%mod;
	printf("%lld",flag1?1:(ans+flag2));
	return 0;
}

标签:return,16,int,LL,ret,fpow,freopen,2023.8,模拟
From: https://www.cnblogs.com/dzrblog/p/17636391.html

相关文章

  • 8016: 重新排序 差分
    描述 给定一个数组 A 和一些查询 Li,Ri,求数组中第 Li 至第 Ri 个元素之和。小蓝觉得这个问题很无聊,于是他想重新排列一下数组,使得最终每个查询结果的和尽可能地大。小蓝想知道相比原数组,所有查询结果的总和最多可以增加多少?  输入 输入第一行包含一个整数......
  • 2023.8.16
    今天没做什么,主要是栈溢出差不多学完了,想花点时间再把基础打好一点今天去b站找到个pwn的视频,最近打算去看一下其中有关gdb调试的相关东西,恰好我调试相关的东西只会一点最简单的,想更好地去做pwn题,感觉这方面还是要学好。中间应该也会去找一些题目来做考虑到九月有竞赛,我在此之前......
  • 闲话8.16
    今天完完整整的在二南度过了一天,不算很舒服......
  • 20230816比赛
    T1矩形Description现在我们在一个平面上画了n个矩形。每一个矩形的两边都与坐标轴相平行,且矩形定点的坐标均为整数。现我们定义满足如下性质的图形为一个块:每一个矩形都是一个块;如果两个块有一段公共的部分,那么这两个块就会形成一个新的块,否则这两个块就是不同的。示......
  • 「Log」2023.8.16 小记
    序幕早上昏迷,九点才到校,少听了四道题,问题不大。点咖啡喝。SAM题也抽象。线段树合并,不会。写个AC自动机板子。\(\color{royalblue}{P3808\【模板】AC\自动机(简单版)}\)板子。\(\text{Link}\)\(\color{royalblue}{P3796\【模板】AC\自动机(加强版)}\)板子。\(\text{Li......
  • string类的模拟实现
    一、C语言中的string类C语言中,字符串是以‘\0’结尾的一些字符集合,为了操作方便,C标准库中提供了一些str系列的库函数,但这些库函数与字符串是分离的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会访问越界。二、C++中的string类1、string类string类的文档介绍:cplus......
  • stack模拟实现
    stack模拟实现我们用适配器模式/配接器模式,本源是转换,把已有的东西进行转换。设计模式:把常见的设计方法进行总结,适配器也是一种设计模式。我们用已有的容器封装:可以这样定义类模板template<classT,classContainer>,Container就是符合我们要求的一个容器。我们可以将头文件写在......
  • 8.16 模拟赛小结
    前言最____的一集题目是从正睿OI捞过来的找不到原题T1文件改名\(n\leq10^5\)题意简要:有一堆文件要改名保证初始的和改正后的名字都没重复且更改过程中不予许出现重复求最小操作步数思考:这题推一下就行若是状态转移把这个东西丢到图上发现可以直接跳过\(s_i=t_i......
  • 模拟集成电路设计系列博客——1.1.3 Cascode电流镜
    1.1.3Cascode电流镜Cascode电流镜是一种高输出阻抗电流镜,其基本结构如下图所示:首先从\(Q_2\)漏极看进去的输出阻抗仅为\(r_{ds2}\),其分析和基本电流镜非常一样。因此可以认为\(Q_4\)是一个带有\(r_{ds2}\)的源极退化电阻的电流源,利用之前的\((1.1.10)\)公式,可以得到:\[r_{out}......
  • 8.16
    #include<iostream>#include<bits/stdc++.h>#definelllonglongusingnamespacestd;constintmaxn=105;queue<char>v[maxn];///存储每个轨道上的物品stack<char>s;///筐queue<char>q;///结果输出intmain(){intN,M,S;int......