题意:
给定一个可以穿越墙体的微观粒子(寿命为 k),但是每穿越一次墙体会产生一个反向寿命为 k−1 的粒子。(如果粒子寿命为1则不再产生反向粒子,即不存在寿命小于1的粒子)
问最后有多少粒子飞出
结合数据 2 3 和下图理解看
题解:
其实就是推导公式:
n为还要穿多少个墙,k为当前能量,cur为方向(1位向右)
最后退出公式:
dfs(int n,int k,int cur) = dfs(n-1,k,cur)+dfs(x-n,k-1,cur^1)
超时!
我用了dp优化
超时!
。。。。
题解
然后看了别人的题解
本质思路一样都是推式子,但是人家有剪枝
solve(cur,k,dir)
cur为该粒子经过了多少强,k为能量,dir为方向
(好像和我定义的差不多)
然后根据不同的方向分情况,详细看代码把
我也说不上来比我的快多少
第一个是我的,在本地运行出不来结果
第二个是正确答案的
等会。。。我交到cf后,A了????
最上面是网上的ac代码,最下面是我的
代码:
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);
return s*w;
}
const int mod=1e9+7;
const int maxn=1e3+8;
int dp[maxn][maxn][3];
int x,y;
int dfs(int n,int k,int cur)
{
if(n==0)return 1;
if(k==1)return 1;
if(dp[n][k][cur]!=-1)return dp[n][k][cur];
// if(n==1)//如果遇到最后一个墙
// {
// return ((dp[n-1][k][cur]=dfs(n-1,k,cur))%mod+(dp[x-n][k-1][cur^1]=dfs(x-n,k-1,cur^1))%mod)%mod;
// }
// else if(n==x)//如果遇到第一个墙
// {
// return ((dp[n-1][k][cur]=dfs(n-1,k,cur))%mod+(dp[0][k-1][cur^1]=dfs(0,k-1,cur^1))%mod)%mod;
// }
int ans1=dfs(n-1,k,cur)%mod;
// dp[n-1][k][cur]=ans1;
int ans2=dfs(x-n,k-1,cur^1)%mod;
// dp[x-n][k-1][cur^1]=ans2;
dp[n][k][cur]=(ans1+ans2)%mod;
return (ans1+ans2)%mod;
}
int main()
{
int t;
cin>>t;
for(int i=1;i<=t;i++)
{
memset(dp,-1,sizeof(dp));
cin>>x>>y;
cout<<dfs(x,y,1)%mod<<endl;
}
return 0;
}
const int mod = 1e9 + 7;
int n, k;
int dp[1010][1010][2];
int solve(int cur, int k, int dir) {
if (k == 1) return 1;
// 非 -1 说明已经计算过了
if (dp[cur][k][dir] != -1) return dp[cur][k][dir];
int ans = 2; // 本身和穿过墙的复制体
if (dir == 1) {
if (cur < n) ans += solve(cur + 1, k, dir) - 1;
ans %= mod;
if (cur > 1) ans += solve(cur - 1, k - 1, 1 - dir) - 1;
ans %= mod;
dp[cur][k][dir] = ans;
} else {
if (cur > 1) ans += solve(cur - 1, k, dir) - 1;
ans %= mod;
if (cur < n) ans += solve(cur + 1, k - 1, 1 - dir) - 1;
ans %= mod;
dp[cur][k][dir] = ans;
}
return ans;
}
int main() {
ios_base::sync_with_stdio(false), cin.tie(0);
int _;
for (cin >> _; _--;) {
cin >> n >> k;
memset(dp, -1, sizeof dp);
cout << solve(1, k, 1) << '\n';
}
return 0;
}