2022五一爆零记总结二

五一第三天 ,被关在学校不能出去玩QAQ
第一题结论推炸了,打表看到1、2、5该想到是卡特兰数的
第二题想到过分块但是觉得太麻烦于是就没有打诶嘿
第三题题目做法是推出来了的,容斥DFS写炸最后竟然还有20分


第一题 数列

题面在下面啦

点击查看题目
数列(sequence.c/cpp/pas)
1 题目描述
我们称一个长度为 2n 的数列是有趣的,当且仅当该数列满足以下三个条件:
 (1)它是从 12n 共 2n 个整数的一个排列{ai};
 (2)所有的奇数项满足 a1<a3<…<a2n-1,所有的偶数项满足 a2<a4<…<a2n;
 (3)任意相邻的两项 a2i-1与 a2i(1i≤n)满足奇数项小于偶数项,即:a2i-1<a2i。
 现在的任务是:对于给定的 n,请求出有多少个不同的长度为 2n 的有趣的数列。因为
最后的答案可能很大,所以只要求输出答案 mod P 的值。
2 输入格式
输入文件只包含用空格隔开的两个整数 n 和 P3 输出格式
仅含一个整数,表示不同的长度为 2n 的有趣的数列个数 mod P 的值。
4 样例输入
  3 6
5 样例输出
  5
6 数据范围与约定
 对于 30%的数据满足 n≤1000;
 对于另外 30%的数据满足 P 为质数;
 对于 100%的数据满足 n≤1000000P1000000000

image

image

代码如下

点击查看代码
#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int f=1,j=0;char w=getchar();
	while(w>'9'||w<'0'){
		if(w=='-')f=-1;
		w=getchar();
	}
	while(w>='0'&&w<='9'){
		j=(j<<3)+(j<<1)+w-'0';
		w=getchar();
	}
	return f*j;
}
const int N=2000001;
bool use[N];
int zhi[N],f[N],tail,n,mod;
int sumi(int sum,int num){
	long long ansn=1,nown=sum;
	while(num>0){
		if(num&1)ansn=ansn*nown%mod;
		num/=2;
		nown=nown*nown%mod;
	}
	return ansn;
}
signed main(){
	//freopen("sequence.in","r",stdin);
	//freopen("sequence.out","w",stdout);
	n=read();mod=read();
	for(int i=2;i<=n*2;i++){
		if(!use[i])zhi[++tail]=i;
		for(int u=1;u<=tail&&zhi[u]*i<=n*2;u++)use[zhi[u]*i]=true;
	}
	for(int i=1;i<=tail;i++){
		for(int u=1;zhi[i]*u<=2*n;u++){
			int a=zhi[i]*u;
			if(zhi[i]*u<=n){
				while(a%zhi[i]==0){
					f[i]--;
					a/=zhi[i];
				}
			}
			if(zhi[i]*u>n+1){
				while(a%zhi[i]==0){
					f[i]++;
					a/=zhi[i];
				}
			}
		}
	}
	long long ans=1;
	for(int i=1;i<=tail;i++){
		if(f[i]==0)continue;
		ans=ans*sumi(zhi[i],f[i])%mod;
	}
	printf("%d",ans);
	return 0;
}

第二题 乘法

题面如下点击查看

点击查看代码
乘法 (mul.c/cpp/pas)
1 题目描述
  输入一个 n ∗ n 的矩阵 A,请求出 A^1+A^2+...+A^k 对 m 取模的结果。
2 输入格式
  第一行为三个正整数 n, k, m,含义如上所述;
  接下来 n 行,每行输入 n 个非负整数,用于描述矩阵 A。
3 输出格式
  输出 n 行,每行 n 个整数,表示答案矩阵。
4 样例输入
  2 2 5
  2 1
  0 3
5 样例输出
  1 1
  0 2
6 数据范围与约定
  对于前 30% 的数据,k<=30;
  对于另外 30% 的数据,n=1;
  对于 100%的数据,n<=30, k<=10^9, m<=10^4
4,输入矩阵的数在 0~m-1 范围内。

不得不说矩阵套矩阵然后推快速幂的方法真的是非常的妙啊...

image
代码如下

点击查看代码
#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int f=1,j=0;char w=getchar();
	while(w>'9'||w<'0'){
		if(w=='-')f=-1;
		w=getchar();
	}
	while(w>='0'&&w<='9'){
		j=(j<<3)+(j<<1)+w-'0';
		w=getchar();
	}
	return f*j;
}
const int N=31,M=32;
int n,k,mod;
struct matrix{
	int s[N][N];
	matrix operator *(const matrix &a)const{
		matrix b;
		for(int x=1;x<=n;x++){
			for(int y=1;y<=n;y++){
				long long ansn=0;
				for(int i=1;i<=n;i++)ansn=(ansn+s[x][i]*a.s[i][y])%mod;
				b.s[x][y]=ansn;
			}
		}
		return b;
	}
	matrix operator +(const matrix &a)const{
		matrix b;
		for(int x=1;x<=n;x++){
			for(int y=1;y<=n;y++){
				b.s[x][y]=(s[x][y]+a.s[x][y])%mod;
			}
		}
		return b;
	}
}mid,yuan,kong;
struct node{
	matrix line[2][2];
	node operator *(const node &a)const{
		node b;
		for(int i=0;i<=1;i++){
			for(int u=0;u<=1;u++){
				b.line[i][u]=line[i][0]*a.line[0][u];
				b.line[i][u]=b.line[i][u]+(line[i][1]*a.line[1][u]);
			}
		}
		return b;
	}
}sta;
node sumi(int tim){
	node nown=sta,ansn;
	ansn.line[0][0]=ansn.line[1][1]=yuan;
	ansn.line[1][0]=ansn.line[0][1]=kong;
	while(tim>0){
		if(tim%2==1)ansn=ansn*nown;
		tim/=2;
		nown=nown*nown;
		
	}
	return ansn;
}
signed main(){
	//freopen("mul.in","r",stdin);
	//freopen("mul.out","w",stdout);
	n=read();k=read();mod=read();
	for(int i=1;i<=n;i++)yuan.s[i][i]=1;
	for(int i=1;i<=n;i++)for(int u=1;u<=n;u++)mid.s[i][u]=read();
	sta.line[0][0]=yuan;
	sta.line[0][1]=mid;
	sta.line[1][1]=mid;
	sta.line[1][0]=kong;
	node ansn=sumi(k-1);
	matrix ans;
	ans=ansn.line[0][0]*mid+ansn.line[0][1]*mid;
	for(int i=1;i<=n;i++){
		for(int u=1;u<=n;u++)printf("%d ",ans.s[i][u]);
		printf("\n");
	} 
	return 0;
}

第三题 生物

题面如下(点击查看)

点击查看代码
生物 (creature.c/cpp/pas)
1 题目描述
  在一个无限长的一维空间中,存在着一个奇特的生物,它的身体上顺次有着 n + 1 个刻印,每个刻印可以用一个正整数来表示。已知它最后一个刻印的值为m,而其它 n 个刻印的值均不超过 m,并且两个刻印的值可以相同。
这个生物每次可以选中它的任意一个刻印,并且按照这个刻印的值 k,选择向它所在位置的前或后闪烁 k 个单位。我们称可以使得这个生物能够通过若干次闪烁,到达一维空间任何一个位置的刻印序列为超刻印序列。
现在刻印序列显然一共有 m^n 种,为了研究这个生物,请你求出其中超刻印序列的数目。
2 输入格式
  仅一行两个整数,分别为 n, m。
3 输出格式
  输出一行一个整数,表示超刻印序列的数目对 10^9+7 取模的结果。
4 样例输入
  2 4
5 样例输出
  12
6 数据范围与约定
  对于前 20%的数据,保证 n,m <= 5;
 对于 100%的数据,保证 1<=n<=15,1<=m<=10^8。

一切的一切都源于ax+by=gcd(x,y)
image
代码如下

点击查看代码
#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int f=1,j=0;char w=getchar();
	while(w>'9'||w<'0'){
		if(w=='-')f=-1;
		w=getchar();
	}
	while(w>='0'&&w<='9'){
		j=(j<<3)+(j<<1)+w-'0';
		w=getchar();
	}
	return f*j;
}
const int N=16,M=100000001,mod=1000000007;
int n,m,ans=1;
int mi[35],cut,zhi[10001],f[10001],tail,len;
int kkk[10001];
bool use[10001];
int sumi(int sum,int num){
	int ansn=1;
	mi[0]=sum;
	for(int i=1;i<=33;i++)mi[i]=1ll*mi[i-1]*mi[i-1]%mod;
	for(int i=0;i<=33&&num>0;i++){
		if(num%2==1)ansn=(1ll*ansn*mi[i])%mod;
		num/=2;
	}
	return ansn;
}
void rongchi(int aim,int tim,int nown,int front){
	if(tim==aim+1){
		kkk[aim]=(kkk[aim]+sumi(m/nown,n))%mod;
		return ;
	}
	for(int i=front+1;i<=len;i++){
		if(!use[i]){
			use[i]=true;
			rongchi(aim,tim+1,nown*f[i],i);
			use[i]=false;
		}
	}
	return ;
}
signed main(){
	//freopen("creature.in","r",stdin);
	//freopen("creature.out","w",stdout);
	for(int i=2;i<=10000;i++){
		if(!use[i])zhi[++tail]=i;
		for(int u=1;u<=tail;u++)if(zhi[u]*i<=10000)use[zhi[u]*i]=true;
	}
	n=read();m=read();
	int a=m;
	for(int i=1;i<=tail&&zhi[i]<=a;i++){
		if(a%zhi[i]==0)f[++len]=zhi[i];
		while(a%zhi[i]==0){
			a/=zhi[i];
		}
	}
	if(a!=1)f[++len]=a;
	memset(use,0,sizeof(use));
	for(int i=1;i<=len;i++)rongchi(i,1,1,0);
	ans=sumi(m,n);
	long long ansn=0;
	for(int i=1;i<=len;i++){
		if(i%2==1)ansn=(ansn+kkk[i])%mod;
		else ansn=(ansn-kkk[i])%mod;
	}
	printf("%d",((ans-ansn)%mod+mod)%mod);
	return 0;
}
posted @   flywatre  阅读(31)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示