8.25总结
A.幸福
因为n的数据范围为\(10^{18}\),所以O(n)和O(\(\sqrt{n}\))的做法是不行的,我就考虑这道题可能是结论题能够用公式O(1)完成。在考场上打表找规律找了好久,我都没找到规律,最后写了O(n)的做法,得到70pts。但这道题其实没有O(1)的公式。
以下是这道题的真实做法。因为可以推出&F_{n}=F_{n-1}+F{n-2}+f_{n}&,且\(n\leq 10^{18}\),所以我们考虑用矩阵快速幂来求\(F_{n}\)的前缀和。
设计矩阵为:
\(\begin{bmatrix}1&1&1&1&0\\1&0&0&0&0\\0&0&1&1&0 \\0&0&1&0&0 \\1&1&1&1&1 \end{bmatrix}\)
答案矩阵为:
\(\begin{bmatrix}F_{n}&F_{n-1}&f_{n}&f_{n-1}&S_{n}\end{bmatrix}\),\(S_{n}=\sum_{i=0}^{n}{F_{i}}\)
矩阵乘法核心代码:
AC Code
void multi(ll c[][N],ll a[][N],ll b[][N])
{
ll tmp[N][N]={0};
for(int i=1;i<=5;i++)
{
for(int j=1;j<=5;j++)
{
for(int k=1;k<=5;k++)
{
tmp[i][j]=(tmp[i][j]+a[i][k]%mod*b[k][j]%mod)%mod;
}
}
}
for(int i=1;i<=5;i++)
{
for(int j=1;j<=5;j++)
{
c[i][j]=tmp[i][j]%mod;
}
}
}
void qow(ll x)
{
ll res[N][N]={0};
ll d[N][N]={0};
d[1][1]=d[1][2]=d[1][3]=d[1][4]=1;
d[2][1]=1;
d[3][3]=d[3][4]=1;
d[4][3]=1;
d[5][1]=d[5][2]=d[5][3]=d[5][4]=d[5][5]=1;
for(int i=1;i<=5;i++)res[i][i]=1;
while(x)
{
if(x&1)multi(res,res,d);
multi(d,d,d);x>>=1;
}
memset(d,0,sizeof d);
d[1][1]=2;
d[2][1]=1;
d[3][1]=1;
d[4][1]=1;
d[5][1]=3;
multi(d,res,d);
printf("%lld\n",d[5][1]%mod);
}
要点:
- 你是否开了long long
- qow函数中的x你是否开了long long
- qow函数中的res和d数组是否清零
- 如果以上都对,检查进行矩阵乘法的两个矩阵是否写反
- 如果以上还是对的,那基本上就是公式推错了
事实给了我惨痛的教训,一定要清零,卡了我将近两个小时才发现问题。
B.奇怪的道路
吸取昨天的教训,在看到\(k\leq 8\)时,我就猜到要用状压DP来解决,但完全不知道如何设计状态啊,预计10pts,事实上0pts。
因为是无向图,我们可以只考虑i与前k个点的连边。因为k很小,我们可以把前k个点的奇偶性变成二进制。
设计状态:\(f_{i,j,s,p}\)表示第i个点,已经连了j条边,前k个点奇偶性为s,且只连了(i-k)~(i-p-1)的点的方案数
转移方程:
\[f_{i,j,s,p-1}+=f_{i,j,s,p}
\]
\[if(i>p)f_{i,j+1,s\oplus 1\oplus 2^{p},p}+=f_{i,j,s,p}
\]
\[if(!(s&(2^k)))f_{i+1,j,s*2,min(i,k)}+=f_{i,j,s,0}
\]
初始状态:\(f_{1,0,0,0}=1\)
目标状态:\(f_{n,m,0,0}\)
AC Code
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
int n,m,k;
int f[35][35][1025][35];
int main()
{
cin>>n>>m>>k;
f[1][0][0][0]=1;
for(int i=1;i<=n;i++)
{
for(int j=0;j<=m;j++)
{
for(int s=0;s<(1<<(k+1));s++)
{
for(int p=min(i-1,k);p;p--)
{
(f[i][j][s][p-1]+=f[i][j][s][p])%=mod;
if(i>p)(f[i][j+1][s^1^(1<<p)][p]+=f[i][j][s][p])%=mod;
}
if(!(s&(1<<k)))
{
(f[i+1][j][s<<1][min(i,k)]+=f[i][j][s][0])%=mod;
}
}
}
}
cout<<f[n][m][0][0]<<endl;
return 0;
}

浙公网安备 33010602011771号