#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n, a[52];
ll k;
bool vis[55][55][2][2];
ll dp[55][55][2][2];
ll ans; ll cnt = 0;
ll dfs(int l,int r,int rev,int inv)
{
if(l>r)return 1;
if(vis[l][r][rev][inv]==true) return dp[l][r][rev][inv];
vis[l][r][rev][inv] =true;//不用vis会超时 中间会遇到很多相同的情况 ex: 49 40394027154620 ->repeat = 2.4k
ll &ans=dp[l][r][rev][inv];
ans = 0;
for(int i=0;i<2;i++)
{
if(a[l] == -1 || a[l] == i)
{
for(int j = 0; j < 2; j++)
{
if(a[r] == -1 || a[r] == j)
{
if(l < r || i == j) //特判n为奇数的时候,走到最中间的一位
{
if(rev || i <= j) //rev = 0 1..l n-1..r identical
{
if(inv || i <= 1 - j) //inv = 0 1..l ~(n-1..r) identical
{
ans = ans + dfs(l + 1, r - 1, rev || i < j , inv || i < 1 - j);
}
}
}
}
}
}
}
return ans;
}
int main()
{
memset(a,-1,sizeof(a));
cin>>n>>k;
k++; //0000...0000不允许 而0-1-1-1...的情况肯定会算进0000...0000
a[0]=0;
if(dfs(0,n-1,0,0)<k){
return 0*puts("-1");
}
for(int i=1;i<n;i++)
{
a[i]=0;
/* puts("before");
for (int j= 0; j<n; j++){
cout<<a[j];
}
puts("");*/
memset(vis,0,sizeof(vis));
ll cur=dfs(0,n-1,0,0);
if(cur<k)
{
k -= cur;
a[i]=1;
}
/*puts("after");
for (int j= 0; j<n; j++){
cout<<a[j];
}
puts("");
cout<<cur<<endl;*/
}
return 0;
}
补充题解集: 从左到右一位一位确定是0还是1 然后先假设该位是0 dp一下 发现不够的话 换成1 以为如果改为是1 肯定囊括了前面0的情况 然后再计算后面的 所以要k -= cur;
Codeforces 8E
最新推荐文章于 2020-07-31 13:31:59 发布