C. Planar Reflections
题目大意
给你一个粒子,n面墙,衰变周期为k,当遇到一面墙时,会分裂出有一个周期为k-1的粒子,并朝反向运动,当衰变周期变为1时,该粒子就不会分裂了,问会分成多少个粒子。
思路
每个粒子的运动方向不会改变,那么到最后不会分裂情况有2种,一种是粒子还能分裂但是,运动方向前面已经没有墙了,还有一种就是,粒子运动方向有墙,但衰变周期,已经变为了1,无法分裂。那么在往上一维考虑,在面临第i(i<n)面墙的粒子(k>1),它会向后继续穿行到第i+1面墙,同时分裂出周期为k-1的粒子,反向运动面临i-1面墙,那么就可以推出dp公式了,dp[i][j]=dp[n-i][j]+dp[i-1][j-1];
在dp过程中第一层先遍历状态,第二层循环再遍历墙数,如果先遍历墙数,有些状态可能还没有更新到的,再通俗点来说,分裂是有先后顺序的,第一个粒子都分裂完了,再来讨论周期·k-1的粒子
通过代码
#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
#pragma GCC optimization ("unroll-loops")
using namespace std;
#define ll long long
#define sl(n) scanf("%lld",&n)
#define pl(n) printf("%lld",n)
#define sdf(n) scanf("%lf",&n)
#define pdf(n) printf("%.lf",n)
#define pE printf("\n")
#define ull unsigned long long
#define pb push_back
#define pre(n) for(ll i=1;i<=n;i++)
#define rep(n) for(ll i=n;i>=1;i--)
#define pi pair<ll,ll>
#define fi first
#define se second
ll dp[1010][1010];
const ll mm= 1e9+7;
int main(){
ll t,n,k,j,i;
sl(t);
while(t--){
// dp[i][j]=dp[i-1][j]+dp[n-i][j-1];
//dp[0][j]=1,dp[x][1]=1;
sl(n),sl(k);
for(i=0; i<=n; i++){
for(j=0; j<=k; j++){
dp[i][j]=0;
if(j!=0) dp[0][j]=1;
dp[i][1]=1;
}
}
for(i=1;i<=k ; i++){
for ( j=1;j<=n ; j++){
dp[j][i] = (dp[j-1][i]+dp[n-j][i-1])%mm;
}
}
cout<<dp[n][k]<<endl;
}
return 0;
}