F. Igor and Mountain

题目链接👈

题目描述🥰

题目思路😀

这道题最关键的是对于题目意思的理解,理解了题意问题就解决了一半🤠

首先这个题目的意思就是从最低点开始攀爬,每一层都有把手,我们需要借助每层的把手攀爬到顶部,但是我们有几条限制条件,1.我们不能爬着爬着又爬到下一层,只能使用同层的把手或者是上面一层的把手,2.每一层我们最多只能使用2个把手,3.我们从 i 位置的把手攀爬到 j 为止的把手,那么他们的欧几里得距离有一个范围限制d,如果两个把手的距离超过d,那么我们就不能从直接从 i 把手切换到 j 把手。而最终我们需要求的是就是攀爬的不同路径的种类和。

那么题目理解了,思路也就很清晰,我们显然就只需要处理从同层转移过来的把手和从下层转移过来的把手数的方案和就好了,当前面对的是位于(i,j)位置的把手

从下层的把手转移过来的方案数:

我们需要知道爬到(j-d+1,j+d-1)范围里面把手的方案和,很显然下层里面的这些把手可以转移到这个把手上面。

从同层的把手转移过来的方案数:

我们需要就是爬到(j-d,j+d)范围里面把手的方案和,很显然下层里面的这些把手可以转移到这个把手上面。

而我们需要尽可能快的得到给定范围的把手数,我们就可以用前缀和来维护给定区域把手的方案数。

AC代码🧠

// Problem: F. Igor and Mountain
// Contest: Codeforces - Codeforces Round 1013 (Div. 3)
// URL: https://codeforces.com/contest/2091/problem/F
// Memory Limit: 512 MB
// Time Limit: 5000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>

#define dev1(a) cout << #a << '=' << a << endl;
#define dev2(a, b) cout << #a << " = " << a << "  " << #b << " = " << b << endl;
#define dev3(a, b, c) cout << #a << " = " << a << "  " << #b << " = " << b << "  " << #c << " = " << c << endl;
#define dev4(a, b, c, d) cout << #a << " = " << a << "  " << #b << " = " << b << "  " << #c << " = " << c << "  " << #d << " = " << d << endl;
#define dev5(a, b, c, d, e) cout << #a << " = " << a << "  " << #b << " = " << b << "  " << #c << " = " << c << "  " << #d << " = " << d << "  " << #e << " = " << e << endl;
#define vec(a)                         \
    for (int i = 0; i < a.size(); i++) \
        cout << a[i] << ' ';           \
    cout << endl;
#define darr(a, _i, _n)               \
    cout << #a << ':';                \
    for (int ij = _i; ij <= _n; ij++) \
        cout << a[ij] << ' ';         \
    cout << endl;           
#define cin(a,n)           \
     for(int i=0;i<n;i++) \
      cin>>a[i];          
#define endl "\n"
#define pow pim
int pim(int a,int k)
{
    int res=1;
    if(a==0)return 0;
    while(k) 
    {
        if(k&1)res=(int)res*a;
        k>>=1;
        a=(int)a*a;
    }
    return res;
}
#define fi first
#define se second
#define caseT \
    int T;    \
    cin >> T; \
    while (T--)
#define int long long
// #define int __int128

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;

const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int MOD = 998244353;

// const int N = ;
int gcd(int a, int b)
{
    return b ? gcd(b, a % b) : a;
}
 
int lcm(int a, int b)
{
    return a * b / gcd(a, b);
}
string tf(string s,int num)
{
	int _=(int)s.size();
    for(int i=0;i<_;i++)s[i]=(s[i]-'a'+num)%26+'a';
    return s;
}
int qmi(int a,int k,int mod){
	int res=1;
	while(k){
		if(k&1) res=(int)res*a%mod;
		a=(int)a*a%mod;
		k>>=1;
	}
	return res;
}
inline int read()
{
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
using i128 = __int128;
 
std::ostream &operator<<(std::ostream &os, i128 n) {
     if (n == 0) return os << 0;
    string s;
    bool negative = false;
    if (n < 0) {
        negative = true;
        n = -n;
    }
    while (n > 0) {
        s += char('0' + n % 10);
        n /= 10;
    }
    if (negative) os << '-';
    reverse(s.begin(), s.end());
    os << s;
    return os;
}
std::istream& operator>>(std::istream& is, i128& n) {
    string s;
    is >> s;
    n = 0;
    int sign = 1;
    if (!s.empty() && s[0] == '-') {
        sign = -1;
        s = s.substr(1);
    }
    for (char c : s) {
        if (!isdigit(c)) { 
            is.setstate(ios::failbit);  
            return is;
        }
        n = n * 10 + (c - '0');
    }
    n *= sign;
    return is;
}
 
i128 toi128(const std::string &s) {
    i128 n = 0;
    for (auto c : s) {
        n = n * 10 + (c - '0');
    }
    return n;
}
 
i128 sqrti128(i128 n) {
    i128 lo = 0, hi = 1E16;
    while (lo < hi) {
        i128 x = (lo + hi + 1) / 2;
        if (x * x <= n) {
            lo = x;
        } else {
            hi = x - 1;
        }
    }
    return lo;
}

i128 gcd(i128 a, i128 b) {
    while (b) {
        a %= b;
        std::swap(a, b);
    }
    return a;
}
const int N=2010;
int n,m,d,f[N],pre[N];
char s[N][N];
void solve()
{
	memset(f,0,sizeof f);
	memset(pre,0,sizeof pre);
	cin>>n>>m>>d;
	for(int i=n;i>=1;i--)
	  for(int j=1;j<=m;++j)
	    cin>>s[i][j];
	int res=d-1;
	for(int i=1;i<=n;++i)
	{
	  for(int j=1;j<=m;++j)
	  {
	  	  if(s[i][j]=='#') f[j]=0;
		  else
	      {
	      	  if(i==1) f[j]=1;
	      	  else f[j]=(pre[min(m,j+res)]-pre[max(1LL,j-res)-1]+MOD)%MOD;
		  }
	  }
	  for(int j=1;j<=m;++j) pre[j]=(pre[j-1]+f[j])%MOD;
	  for(int j=1;j<=m;++j) if(s[i][j]=='X') f[j]=(pre[min(m,j+d)]-pre[max(1LL,j-d)-1]+MOD)%MOD;
	  for(int j=1;j<=m;++j) pre[j]=(pre[j-1]+f[j])%MOD;
	}
	cout<<pre[m]<<endl;
}

signed main()
{

    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
	caseT
    solve();
    return 0;
}
/*

*/

 

 posted on 2025-03-26 16:54  熙玺  阅读(95)  评论(0)    收藏  举报

Shu-How Zの小窝

Loading...