首页 > 其他分享 >509迷宫

509迷宫

时间:2024-09-07 23:14:03浏览次数:10  
标签:int 509 迷宫 getchar while 对角线 障碍 mod

想法还是太过于巧妙了。

首先有一个很简单的容斥 \(n^2\) 做法。

然后我们能发现 \(mod\) 很小,注意:\(\forall_{1 \le i < mod}\) \(C_{mod}^{i} = 0\)。

所以就有个天才的做法,将矩阵沿着对角线切开,类似这样:

image

如果我们每隔 \(mod\) 进行一次切割,那么我们就会发现如果把第 \(i\) 条对角线转移到 第 \(i+1\) 条的话,就像这样:

image

我们发现对于 \((x,y)\) 只需要转移到 \((x+mod,y)\) 和 \((x,y+mod)\) 就行了,因为其他点的组合数为 \(0\) !

所以 \(dp_{x,i}\) 表示点 \((i,x-i)\) 的方案数,然后转移就是:

  1. 对角线到对角线
  2. 对角线到障碍点
  3. 障碍点到障碍点
  4. 障碍点到对角线

分别做一下就行了。

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
inline int read(){
	int x=0,f=1; char c=getchar();
	while(!isdigit(c)){if(c=='-') f=-1; c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48); c=getchar();}
	return x*f;
}
const int N=3e5+5,mod=509,M=2e5+5;
int n,a[N];
int cc[mod+5][mod+5];
inline int C(int x,int y){return cc[x][y];}
inline void init(){
	cc[0][0]=1;
	for(int i=1;i<=mod;i++){
		cc[i][0]=1;
		for(int j=1;j<=mod;j++) cc[i][j]=(cc[i-1][j]+cc[i-1][j-1])%mod;
	}
}

int f[N],tmp[N],g[N];

vector<int> s[N*2];
signed main(){
    n=read();
	for(int i=1;i<=n;i++) a[i]=read(),s[i+a[i]].push_back(i);
	init(),f[0]=1;
	for(int i=1;i<=2*n/mod;i++){
		int l=(i-1)*mod,r=i*mod;
		int pl=max(0ll,l-n),pr=min(l,n);
		int ll=max(0ll,r-n),rr=min(r,n);
		//line to line
		for(int j=ll;j<=rr;j++){
			tmp[j]=f[j];
			if(j>=mod) (tmp[j]+=f[j-mod])%=mod; 
		}
		for(int j=l+1;j<=r;j++){
			for(auto x:s[j]){
				int L=l-a[x],R=x;
				//point to point
				for(int k=L;k<R;k++) if(l<k+a[k]&&k+a[k]<=r&&a[k]<=a[x]) (g[x]-=g[k]*C(x-k+a[x]-a[k],x-k))%=mod; //(k,a[k]) (x,a[x])

				//line to point
				for(int k=max(pl,L);k<=min(R,pr);k++) (g[x]+=f[k]*C(x+a[x]-l,x-k))%=mod; //(k,(i-1)*mod-k) (x,a[x])
				g[x]=(g[x]+mod)%mod;
				//point to line
				L=x,R=r-a[x];
				for(int k=max(L,ll);k<=min(R,rr);k++) (tmp[k]-=g[x]*C(r-a[x]-x,k-x))%=mod; //(x,a[x]) (k,i*mod-k)
			}
		}
		for(int i=0;i<=rr;i++) f[i]=(tmp[i]+mod)%mod,tmp[i]=0;
	}
	cout<<(f[n]+mod)%mod<<'\n';
}
/*
5
2 4 1 1 2 
*/

标签:int,509,迷宫,getchar,while,对角线,障碍,mod
From: https://www.cnblogs.com/Cyan0826/p/18402311

相关文章

  • 【C++算法全真练习题】迷宫问题
    目录题目描述思路AC解答题目描述‌题目描述‌:‌给定一个二维迷宫,‌其中 0 表示可以走的路,‌1 表示障碍物。‌起点坐标为 (0,0),‌终点坐标为 (m-1,n-1),‌其中 m 和 n 分别是迷宫的行数和列数。‌你需要使用广度优先搜索(‌BFS)‌找到从起点到终点的一条路径......
  • 迷宫,返回所有路径并排序(C++)(回溯+dfs)
    题意说明:要求给出一个m*n的矩阵迷宫,0代表入口,1代表道路,2代表墙体,3代表出口,要求返回从入口到出口的所有移动路径并按长短从小到大排序。移动路径:就是wasd的移动路径,如一共走三步:下,右,下,则输出:sds。代码如下:#include<iostream>#include<string>#include<vector>#include<alg......
  • 代码随想录算法训练营第32天|509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯
    目录509.斐波那契数1、题目描述2、思路3、code4、复杂度分析70.爬楼梯1、题目描述2、思路3、code746.使用最小花费爬楼梯1、题目描述2、思路3、code4、复杂度分析509.斐波那契数题目链接:link1、题目描述斐波那契数(通常用F(n)表示)形成的序列称为斐波那......
  • FINC5090 - Finance in the Global Economy
    FINC5090-FinanceintheGlobalEconomyIndividualAssignmentOutlineSemester2,2024Instructions1. Read the instructions carefully.2. This assignment is worth 25%of total marks for FINC5090.3. The DUE DATE is 6SEPTEMBER 2024. The......
  • C语言阴阳迷宫
    目录开头程序程序的流程图程序游玩的效果下一篇博客要说的东西开头大家好,我叫这是我58。程序#define_CRT_SECURE_NO_WARNINGS1#include<stdio.h>#include<stdlib.h>#include<string.h>#include<Windows.h>enumWASD{ W, A, S, D};enumYYSe{ YI......
  • 牛客小白月赛99 C-迷宫(DFS)
    题目描述给定一个n×m\mathrm{n\timesm}n×m的迷宫,迷宫由"#"与"."两种字符组成。其中"#"代表障碍物,"."表示空地。迷宫中还有一个起点"S"和一个终点"E",它们都可以视为空地。 由于近期迷宫发生了塌方,导致起点和终点之间可能并不连通。幸运的是,你拥有一种超能......
  • 走迷宫小游戏
    #include<stdio.h>#include<conio.h>#include<windows.h>#include<time.h>#defineHeight45#defineWidth45#defineWall1#defineRoad0#defineStart2#defineEnd3#defineEsc5#defineUp1#defineDown2#defineLeft3#d......
  • 洛谷P1605 迷宫
    原题题目描述给定一个方格的迷宫,迷宫里有处障碍,障碍处不可通过。在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。给定起点坐标和终点坐标,每个方格最多经过一次,问有多少种从起点坐标到终点坐标的方案。输入格式第一行为三个正整数,分......
  • 汇编语言之门:深入I/O操作的迷宫
    标题:汇编语言之门:深入I/O操作的迷宫在计算机的微观世界中,汇编语言以其与硬件的紧密联系而著称。输入输出(I/O)操作是汇编语言程序中与外部世界交互的重要手段。本文将带你深入探索汇编语言中的I/O操作,揭示其背后的原理,并展示如何通过代码实现基本的I/O功能。汇编语言与I/O操......
  • 汇编语言之门:深入I/O操作的迷宫
    标题:汇编语言之门:深入I/O操作的迷宫在计算机的微观世界中,汇编语言以其与硬件的紧密联系而著称。输入输出(I/O)操作是汇编语言程序中与外部世界交互的重要手段。本文将带你深入探索汇编语言中的I/O操作,揭示其背后的原理,并展示如何通过代码实现基本的I/O功能。汇编语言与I/O操......