C. 古老的打字机
- 题目往往没有你想象的那么难,所以在否定简单的想法之前,不妨先问问自己这个“漏洞”真的难以解决吗?许多时候,你与正确答案其实只差一步而已
- 本题最朴素的想法就是直接步步转移\(f_{i,j}\),但是这样肯定不对呀,失配的情况怎么体现呢?于是兜兜转转一圈,推出三方做法后面对“卷积”式的转移束手无策。虽然题目一定是可做的,但这并不代表这种“卷积”式的转移一定可以优化,很可能你的大方向就错了,此时就需要你回顾思维过程。
- 其实,当“不匹配”的数填入后,它的故事还没有结束,因为它最终一定是要被删掉的,我们不妨等待一下,延迟到删除它的时候再处理
- 复习一下卡特兰数:关于n个0和n个1的排列,有奇数项为0的特点。但很可惜,它并不能帮你解决这道题
- 用匹配数j划分阶段 f[i][j]=f[i-1][max(j-1,0)]+f[i-1][j+1]*2 之所以有系数2,是因为退格之后我们并不关心上一个数是否填对,所以可以指定0变成1/指1为0,方案数是一样的,要注意此时第二维就不能只递推到m了,而要与n同阶。
#include <bits/stdc++.h>
using namespace std;
const int mod=1000000007;
int f[5005][5005];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin>>n;
string s;
cin>>s;
int m=s.size();
f[0][0]=1;
for(int i=1;i<=n;i++)
{
for(int j=0;j<=n&&j<=i;j++)
{
if(j)
{
f[i][j]=f[i-1][j-1];
}
else
{
f[i][j]=f[i-1][j];
}
f[i][j]=(f[i][j]+f[i-1][j+1]*2%mod)%mod;
}
}
cout<<f[n][m]<<endl;
return 0;
}
D. 倒水问题
- 有趣的一道题,原来小时候做的倒水问题的本质是扩展欧几里得算法呀。如果排行榜上其他同学没有那么快的AC这道题,你也能一下子就想到结论吗?
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin>>T;
while(T--)
{
int a,b,c;
cin>>a>>b>>c;
if(c%__gcd(a,b)==0)
{
cout<<"Yes\n";
}
else
{
cout<<"No\n";
}
}
return 0;
}