ICode9

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

【BZOJ5318】[JSOI2018]扫地机器人(动态规划)

2019-02-23 11:38:53  阅读:325  来源: 互联网

标签:ch gcd JSOI2018 MAX le int 扫地 BZOJ5318 include


【BZOJ5318】[JSOI2018]扫地机器人(动态规划)

题面

BZOJ
洛谷

题解

神仙题。不会。。。。
先考虑如果一个点走向了其下方的点,那么其右侧的点因为要被访问到,所以必定只能从其右上方的点走过来。同理,如果这个点向右,那么其下方的点就只能从其左下方的点向右走过来。
因此我们可以确定所有平行于副对角线的斜线上的位置的方向都是相同的。
考虑\(n=m\)的情况,从一个点开始无论向右开始向下,都只会走到下一条对角线上,因此这个过程本质上就是就是固定了一个向下向右的序列,然后循环这个操作直到结束。
考虑一个序列如果是合法的,假设其向下走\(x\)次,向右走\(n-x\)次,因为是循环这个操作,那么它会走到的列显然就是\(gcd(x,n)\)的倍数,因此当且仅当\(gcd(x,n)=1\)时这个操作序列才会合法。
因此\(n=m\)时答案就是\(\displaystyle \sum_{i=1}^n [gcd(i,n)=1]{n\choose i}\)。
如果\(n\neq m\),令\(d=gcd(n,m)\),(通过看别人写的题解),我们可以知道这个矩形必定被分成若干个\(d*d\)的矩形,并且每个矩形内部的方案都是一样的。(谁会证明就教教我啊QwQ)
那么假设\(i\)是向下走的步数,\(j=d-i\)即向右走的步数。
那么答案就是\(\displaystyle \sum_{i=1}^d[gcd(i,d)=1][gcd(i,n)=1][gcd(j,m)=1]{d\choose i}\)。(\(i,d\)互质和\(j,d\)互质两者是等价的,所以就不用多一个\(j,d\)互质的限制了)
现在考虑有障碍的情况。如果从一个格子\((x,y)\)出发走\(d\)步,那么它必定会到达\((x+i,y+j)\)(因为所有\(d*d\)的矩形都是同构的)。
把题目要求的停止,转为求到达所有障碍的时间的最小值。
把所有障碍分下类,全部可以写成\((x+ki,y+kj)\)的形式,这里的\(1\le x\le i+1,1\le y\le j+1\)。
而最小值只有\(n*m\)个,设\(f[i][j][k]\)表示当前在点\((i,j)\),路径上访问过的障碍的最小值为\(k\)的方案数。
每次枚举合法的一组\(i,j\),然后预处理出离每个\((x+ki,y+kj)\)最近的障碍的距离,这样子就可以大力\(dp\)了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MOD 998244353
#define MAX 55
void add(int &x,int y){x+=y;if(x>=MOD)x-=MOD;}
inline int read()
{
    int x=0;bool t=false;char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=true,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return t?-x:x;
}
int n,m,d,ans,val[MAX][MAX];
int f[MAX][MAX][MAX*MAX];
char g[MAX][MAX];
int Solve(int dx,int dy)
{
    memset(f,0,sizeof(f));
    f[1][1][val[1][1]]=1;
    for(int i=1;i<=dx;++i)
        for(int j=1;j<=dy;++j)
            for(int k=1;k<=n*m;++k)
            {
                if(!f[i][j][k])continue;
                if(i<dx)add(f[i+1][j][min(k,val[i+1][j])],f[i][j][k]);
                if(j<dy)add(f[i][j+1][min(k,val[i][j+1])],f[i][j][k]);
            }
    int ret=0;
    for(int i=1;i<=n*m;++i)ret=(ret+1ll*f[dx][dy][i]*i)%MOD;
    return ret;
}
int main()
{
    int T=read();
    while(T--)
    {
        n=read(),m=read();d=__gcd(n,m);ans=0;
        for(int i=1;i<=n;++i)scanf("%s",g[i]+1);
        for(int i=1,j=d-1;i<=d;++i,--j)
        {
            if(__gcd(i,d)!=1||__gcd(i,n)!=1||__gcd(j,m)!=1)continue;
            for(int x=1;x<=i+1;++x)
                for(int y=1;y<=j+1;++y)
                {
                    int nx=x,ny=y,dis=x+y-2;val[x][y]=n*m;
                    do
                    {
                        if(g[nx][ny]=='1'){val[x][y]=dis;break;}
                        nx+=i;ny+=j;dis+=d;
                        if(nx>n)nx-=n;if(ny>m)ny-=m;
                    }while(nx!=x||ny!=y);
                }
            ans=(ans+Solve(i+1,j+1))%MOD;
        }
        printf("%d\n",ans);
    }
    return 0;
}

标签:ch,gcd,JSOI2018,MAX,le,int,扫地,BZOJ5318,include
来源: https://www.cnblogs.com/cjyyb/p/10422074.html

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

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

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

ICode9版权所有