結果
| 問題 |
No.579 3 x N グリッド上のサイクルのサイズ(hard)
|
| ユーザー |
|
| 提出日時 | 2017-10-14 13:51:42 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 4 ms / 2,000 ms |
| コード長 | 5,216 bytes |
| コンパイル時間 | 1,837 ms |
| コンパイル使用メモリ | 132,476 KB |
| 実行使用メモリ | 5,248 KB |
| 最終ジャッジ日時 | 2024-11-17 14:27:25 |
| 合計ジャッジ時間 | 4,291 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 80 |
ソースコード
#define _USE_MATH_DEFINES
#include <cstdio>
#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <complex>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <limits>
#include <climits>
#include <cfloat>
#include <functional>
#include <iterator>
using namespace std;
const int MOD = 1000000007;
template <class T>
vector<vector<T> > matrixProduct(const vector<vector<T> >& x, const vector<vector<T> >& y)
{
int a = x.size();
int b = x[0].size();
int c = y[0].size();
vector<vector<T> > z(a, vector<T>(c, 0));
for(int i=0; i<a; ++i){
for(int j=0; j<c; ++j){
for(int k=0; k<b; ++k){
z[i][j] += x[i][k] * y[k][j];
z[i][j] %= MOD;
}
}
}
return z;
}
template <class T>
vector<vector<T> > matrixPower(const vector<vector<T> >& x, long long k)
{
int n = x.size();
vector<vector<T> > y(n, vector<T>(n, 0));
for(int i=0; i<n; ++i)
y[i][i] = 1; // 積の単位元
vector<vector<T> > z = x;
while(k > 0){
if(k & 1)
y = matrixProduct(y, z);
z = matrixProduct(z, z);
k >>= 1;
}
return y;
}
string normalizeState(string s)
{
char newChar = 'A';
map<int, int> to;
to['.'] = '.';
int n = s.size();
string ans(n, '.');
for(int i=0; i<2; ++i){
string t(n, '.');
for(int j=0; j<n; ++j){
if(to.find(s[j]) == to.end()){
to[s[j]] = newChar;
++ newChar;
}
t[j] = to[s[j]];
}
ans = max(ans, t);
reverse(s.begin(), s.end());
}
return ans;
}
void makeState(int len, vector<string>& state)
{
vector<set<string> > nonEmptyState(len+1);
nonEmptyState[0].insert("");
for(int i=0; i<len; i+=2){
for(const string s : nonEmptyState[i]){
string t1 = normalizeState(s + "ZZ");
string t2 = normalizeState('Z' + s + 'Z');
nonEmptyState[i+2].insert(t1);
nonEmptyState[i+2].insert(t2);
}
}
set<string> preState;
for(int i=0; i<(1<<len); ++i){
bitset<32> bs(i);
for(const string s : nonEmptyState[bs.count()]){
int k = 0;
string t(len, '.');
for(int j=0; j<len; ++j){
if(bs[j]){
t[j] = s[k];
++ k;
}
}
preState.insert(normalizeState(t));
}
}
state = vector<string>(preState.begin(), preState.end());
}
long long solve(long long n, int len)
{
vector<string> state;
makeState(len, state);
int stateNum = state.size();
vector<vector<long long> > mat(stateNum*2+1, vector<long long>(stateNum*2+1, 0));
mat[stateNum*2][stateNum*2] = 1;
for(int a=0; a<stateNum; ++a){
const string& s = state[a];
bitset<32> upper;
for(int i=0; i<len; ++i)
upper[i] = (s[i] != '.');
for(int i=0; i<(1<<(len-1)); ++i){
bitset<32> side(i << 1);
bool ng = false;
int cnt = 0;
for(int j=0; j<len; ++j){
if(upper[j] && side[j] && side[j+1])
ng = true;
if(upper[j] || side[j] || side[j+1])
++ cnt;
}
if(ng)
continue;
string t = s;
int sameCnt = 0;
char newChar = 'Z';
for(int j=0; j<len; ++j){
if(!side[j]){
int k = j;
while(side[k+1])
++ k;
if(j < k){
if(s[j] == '.' && s[k] == '.'){
t[j] = t[k] = newChar;
-- newChar;
}
else if(s[j] == '.' || s[k] == '.'){
swap(t[j], t[k]);
}
else if(s[j] == s[k]){
t[j] = t[k] = '.';
++ sameCnt;
}
else{
replace(t.begin(), t.end(), s[j], s[k]);
t[j] = t[k] = '.';
}
}
}
}
if(sameCnt >= 2 || (sameCnt == 1 && t != string(len, '.')))
continue;
if(t == string(len, '.') && cnt > 0){
++ mat[stateNum*2][a+stateNum];
mat[stateNum*2][a] += cnt;
}
else{
t = normalizeState(t);
int b = find(state.begin(), state.end(), t) - state.begin();
++ mat[b][a];
++ mat[b+stateNum][a+stateNum];
mat[b+stateNum][a] += cnt;
}
}
}
mat = matrixPower(mat, n+1);
return mat[stateNum*2][0];
}
int main()
{
long long n;
cin >> n;
cout << solve(n, 4) << endl;
return 0;
}