A. 【UR #16】破坏发射台
题解:
首先看n是偶数的
那么就是不需要满足对面这个性质的
这样就可以dp了 f[i][0/1]表示dp到第i位,当前数等于或不等于第一位的方案数
然后显然可以用矩阵优化
再考虑n为奇数
用一样的思路,把环切成两半,先确定两个对应位置的值,再进行dp
f[i][0/1/2][0/1/2]表示dp到i位,下面这个数等不等于上面第一个,等不等于下面第一个(同理上面)
发现这个可以dp,依旧用矩阵优化一波
转移方程稍微有点复杂,有个对拍就轻松多了
另外注意f不能表示成f[i][0/1][0/1]表示和不同侧的起始点
原因是这样转移的时候会出现问题,无法确定它旁边的点和同侧的起始点之间的颜色关系(非常的绕口)
注意别少取模
#include <bits/stdc++.h>
using namespace std;
#define ll long long
struct re{
ll a[10][10];
}aa;
ll a[9][9],n,m;
#define mo 998244353
re XX(re x,re y)
{
re tmp;
memset(tmp.a,0,sizeof(tmp.a));
for (ll i=1;i<=8;i++)
for (ll j=1;j<=8;j++)
for (ll k=1;k<=8;k++)
tmp.a[i][k]+=x.a[i][j]*y.a[j][k],
tmp.a[i][k]%=mo;
return tmp;
}
re fast_pow(ll x)
{
if (x==1) return(aa);
re b=fast_pow(x/2);
b=XX(b,b);
if (x%2==1) b=XX(b,aa);
return (b);
}
int main()
{
freopen("noip.in","r",stdin);
freopen("noip.out","w",stdout);
cin>>n>>m;
if (n%2==0)
{
a[1][1]=(m-4)*(m-4)+(m-3);
a[1][2]=a[1][3]=a[1][4]=a[1][7]=(m-3)*(m-4)+(m-3);
a[1][6]=a[1][8]=(m-2)*(m-3);
a[2][1]=a[2][3]=m-3;
a[2][4]=a[2][6]=a[2][7]=m-2;
a[3][2]=a[3][1]=m-3;
a[3][4]=a[3][7]=a[3][8]=m-2;
a[4][1]=a[4][7]=m-3;
a[4][2]=a[4][3]=a[4][8]=m-2;
a[7][1]=a[7][4]=m-3;
a[7][2]=a[7][3]=a[7][6]=m-2;
a[6][1]=a[6][2]=a[6][7]=a[6][8]=1;
a[8][1]=a[8][3]=a[8][4]=a[8][6]=1;
for (ll i=1;i<=8;i++)
for (ll i=1;i<=8;i++)
for (ll j=1;j<=8;j++)
aa.a[i][j]=max(0*1ll,a[i][j]%mo);
/* for (ll i=1;i<=8;i++)
{
for (ll j=1;j<=8;j++)
cout<<aa.a[i][j]<<" ";
cout<<endl;
}
cout<<endl<<endl;*/
re x=fast_pow(n/2-1);
/* for (ll i=1;i<=8;i++)
{
for (ll j=1;j<=8;j++)
cout<<x.a[i][j]<<" ";
cout<<endl;
}*/
ll ans=x.a[1][8]+x.a[2][8]+x.a[7][8]+x.a[8][8];
ans=(ans*m)%mo*(m-1);
ans=(ans%mo+mo)%mo;
cout<<ans;
}
return 0;
}