返回顶部

CodeCraft-21 and Codeforces Round #711 (Div. 2) C. Planar Reflections (DP)

  • 题意:有\(n\)块板子,一个能量为\(k\)的粒子,粒子可以直接穿过板子,当粒子穿过一个板子时,会产生一个反方向的能量为\(k-1\)的粒子,不存在能量为\(0\)的粒子,问你将能量为\(k\)的粒子从最左边向板子射出时,会产生多少粒子?

  • 题解:我们记\(dp[i][j]\),表示能量为\(i\)且要穿过\(j\)个板子的粒子能产生的粒子数,那么当它穿过一个板子时,会有它自己\(dp[i][j-1]\),和产生的新粒子\(dp[i-1][n-j]\),所以可以写出状态转移方程:\(dp[i][j]=dp[i][j-1]+dp[i-1][n-j]\).

  • 代码:

    #include <bits/stdc++.h>
    #define ll long long
    #define fi first
    #define se second
    #define pb push_back
    #define me memset
    #define rep(a,b,c) for(int a=b;a<=c;++a)
    #define per(a,b,c) for(int a=b;a>=c;--a)
    const int N = 1e6 + 10;
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    typedef pair<int,int> PII;
    typedef pair<ll,ll> PLL;
    ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}
    
    int dp[1005][1005];
    
    int main() {
        ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    	int _;
        cin>>_;
        while(_--){
            int n,k;
            cin>>n>>k;
     
            rep(i,1,n) dp[1][i]=1;
            rep(i,1,k) dp[i][0]=1;
     
            rep(i,1,k){
                rep(j,1,n){
                   dp[i][j]=(dp[i][j-1]+dp[i-1][n-j])%mod; 
                }
            }
     
            cout<<dp[k][n]<<'\n';
     
        }
    
        return 0;
    }
    
posted @ 2021-03-31 11:03  _Kolibri  阅读(58)  评论(0)    收藏  举报