結果

問題 No.562 超高速一人かるた small
ユーザー nanophoto12nanophoto12
提出日時 2017-08-27 21:43:45
言語 C++11
(gcc 11.4.0)
結果
AC  
実行時間 831 ms / 3,000 ms
コード長 2,194 bytes
コンパイル時間 753 ms
コンパイル使用メモリ 91,664 KB
実行使用メモリ 11,648 KB
最終ジャッジ日時 2024-04-24 00:27:45
合計ジャッジ時間 11,172 ms
ジャッジサーバーID
(参考情報)
judge1 / judge2
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1 ms
5,248 KB
testcase_01 AC 1 ms
5,376 KB
testcase_02 AC 2 ms
5,376 KB
testcase_03 AC 1 ms
5,376 KB
testcase_04 AC 2 ms
5,376 KB
testcase_05 AC 2 ms
5,376 KB
testcase_06 AC 1 ms
5,376 KB
testcase_07 AC 6 ms
5,376 KB
testcase_08 AC 85 ms
5,376 KB
testcase_09 AC 803 ms
11,648 KB
testcase_10 AC 189 ms
5,376 KB
testcase_11 AC 370 ms
7,424 KB
testcase_12 AC 83 ms
5,376 KB
testcase_13 AC 3 ms
5,376 KB
testcase_14 AC 831 ms
11,392 KB
testcase_15 AC 826 ms
11,648 KB
testcase_16 AC 823 ms
11,648 KB
testcase_17 AC 827 ms
11,520 KB
testcase_18 AC 817 ms
11,520 KB
testcase_19 AC 812 ms
11,520 KB
testcase_20 AC 793 ms
11,520 KB
testcase_21 AC 801 ms
11,520 KB
testcase_22 AC 796 ms
11,392 KB
testcase_23 AC 820 ms
11,520 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <cmath>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <functional>
#include <queue>
#include <iostream>
#include <string.h>
#include <iomanip>
#include <algorithm>
#include <functional>
#include <cstdint>
#include <climits>
#include <unordered_set>
#include <sstream>
#include <stack>

using namespace std;

typedef long long int ll;
typedef pair<int,int> pii;
typedef tuple<ll,ll,ll> t3;

using namespace std;

int N;
string S[202];
ll dp[1<<20];
ll mod=1000000007;
ll fact[21];
ll ret[21];
int cost[20][20];

void solve() {
    
    cin>>N;
    for(int i = 0;i < N;i++)
    {
        cin >> S[i];
    }
    for(int x = 0;x < N;x++)
    {
        for(int y = 0;y < N;y++)
        {
            //2者間コストの計算
            cost[x][y]=1;
            while(cost[x][y]<=S[x].size() && cost[x][y]<=S[y].size() && S[x][cost[x][y]-1]==S[y][cost[x][y]-1])
            {
                cost[x][y]++;
            }
        }
    }
    
    fact[0]=1;
    for(int i = 0;i < N;i++)
    {
        //階乗計算
        fact[i + 1] = fact[i] * (i+1)%mod;
    }
    
    
    for(int mask=0;mask<1<<N;mask++) {
        //bit数
        int b=__builtin_popcount(mask);
        //疲労度
        ret[b] += dp[mask];
        ret[b] %= mod;
        for(int i = 0;i < N;i++)
        {
            //まだ引いていない別の札を取る
            if((mask&(1<<i))==0)
            {
                int ma=1;
                //次に取る札、すでに撮った札以外の札との最大コストを計算する
                for(int x = 0;x < N;x++)
                {
                    if(i == x)
                    {
                        continue;
                    }
                    if((mask&(1<<x))==0)
                    {
                        ma=max(ma,cost[i][x]);
                    }
                }
                //この状態になる組み合わせはb!だけあるため、fact[b]をかける
                dp[mask|(1<<i)] += (dp[mask]+ma*fact[b]);
                dp[mask|(1<<i)] %= mod;
            }
        }
    }
    for(int i=1;i<=N;i++) cout<<ret[i]%mod<<endl;
}

int main()
{
    solve();
    return 0;
}
0