[[AHOI2009] 중국 장기!]

2051 단어
계수류 dp는 그래도 많이 써야 돼요.
보아하니 아무런 사고방식도 없는 데다가 문제풀이에 눌린 라벨에 현혹되어 문제풀이에 디자인된 상태를 한 번 보았다
그다음에 잘 돼요.
우선 이 문제의 본질을 알아야 한다. 즉, 어떤 줄의 포에 대해서도 개수를 초과해서는 안 된다는 것이다. (2\)
우리가\(dp[i][j][k]\)를 설정하면 제\(i\)줄에 모두\(j\)열이 있는 포의 개수는\(2\)이고\(k\)열이\(1\)열인 총방안의 개수가 있음을 나타냅니다.
그렇다면 대포 한 개도 쏘지 않은 열수는 자연히\(m-k-j\)이다
그다음에 막 해도 돼요.
한 줄에 세 가지 선택이 있어요.
  • 놓지 않음
  • 하나
  • 두 개
  • 그다음에 이게 저희의 핵심 사상이에요.
    모두 다섯 가지 이동이 있는데, 바로 간단한 계수 원리와 조합 수학들이다
    코드
    #include
    #include
    #include
    #define re register
    #define maxn 105
    #define LL long long
    const LL P=9999973;
    const LL inv=4999987;//2 P      
    int n,m;
    LL dp[maxn][maxn][maxn];
    int main()
    {
        scanf("%d%d",&n,&m);
        dp[1][0][0]=1;
        dp[1][0][1]=m;
        dp[1][0][2]=m*(m-1)*inv%P;
        for(re int i=1;im) continue;
                    int p=m-k-j;
                    if(!dp[i][j][k]) continue;
                    dp[i+1][j][k]=(dp[i+1][j][k]+dp[i][j][k])%P;//         
                    if(j+1<=m&&k-1>=0) 
                        dp[i+1][j+1][k-1]=(dp[i+1][j+1][k-1]+dp[i][j][k]*k%P)%P;//    1       
                    if(p&&k+1<=m&&j+k+1<=m) 
                        dp[i+1][j][k+1]=(dp[i+1][j][k+1]+dp[i][j][k]*p%P)%P;//    0       
                    if(j+2<=m&&k-2>=0) 
                        dp[i+1][j+2][k-2]=(dp[i+1][j+2][k-2]+(dp[i][j][k]*(k-1)*k%P)*inv)%P;//      1    
                    if(p>=2&&k+2<=m&&j+k+2<=m) 
                        dp[i+1][j][k+2]=(dp[i+1][j][k+2]+(dp[i][j][k]*(p-1)*p)%P*inv)%P;//      0    
                    if(p&&j+1<=m&&k&&j+1+k<=m)
                        dp[i+1][j+1][k]=(dp[i+1][j+1][k]+dp[i][j][k]*k*p%P)%P;//      0,     1   
                    
                }
        LL ans=0;
        for(re int i=0;i<=m;i++)
        for(re int j=0;j<=m;j++)
        if(i+j<=m) ans=(ans+dp[n][i][j])%P;
        std::cout<

    좋은 웹페이지 즐겨찾기