AtCoder Grand Contest 031 (AGC031) F - Permutation and Minimum 动态规划

原文链接www.cnblogs.com/zhouzhendong/p/AGC031F.html

草率题解

对于每两个相邻位置,把他们拿出来。

如果这两个相邻位置都有确定的值,那么不管他。

然后把所有的这些数拿出来,分为两类,一类是没有被填入的,一类是被填入的。

然后大力DP即可。由于没有被填入的可以任意排列,所以最后还要乘上一个阶乘。

代码

#include <bits/stdc++.h>
#define clr(x) memset(x,0,sizeof x)
#define For(i,a,b) for (int i=(a);i<=(b);i++)
#define Fod(i,b,a) for (int i=(b);i>=(a);i--)
#define fi first
#define se second
#define pb(x) push_back(x)
#define mp(x,y) make_pair(x,y)
#define outval(x) cerr<<#x" = "<<x<<endl
#define outtag(x) cerr<<"---------------"#x"---------------"<<endl
#define outarr(a,L,R) cerr<<#a"["<<L<<".."<<R<<"] = ";                        For(_x,L,R)cerr<<a[_x]<<" ";cerr<<endl;
using namespace std;
typedef long long LL;
typedef vector <int> vi;
LL read(){
    LL x=0,f=0;
    char ch=getchar();
    while (!isdigit(ch))
        f|=ch=='-',ch=getchar();
    while (isdigit(ch))
        x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    return f?-x:x;
}
const int N=305*2,mod=1e9+7;
int Pow(int x,int y){
    int ans=1;
    for (;y;y>>=1,x=(LL)x*x%mod)
        if (y&1)
            ans=(LL)ans*x%mod;
    return ans;
}
void Add(int &x,int y){
    if ((x+=y)>=mod)
        x-=mod;
}
void Del(int &x,int y){
    if ((x-=y)<0)
        x+=mod;
}
int Add(int x){
    return x>=mod?x-mod:x;
}
int Del(int x){
    return x<0?x+mod:x;
}
int n;
int a[N],b[N];
int cnt=0,tot=0;
int dp[N][N][N];
vector <int> v;
int main(){
    n=read();
    For(i,1,n*2){
        a[i]=read();
        if (a[i]!=-1)
            b[a[i]]=1;
    }
    For(i,1,n){
        if (a[i*2-1]==-1&&a[i*2]==-1)
            cnt++,tot+=2;
        else if (a[i*2-1]==-1)
            tot+=2,v.pb(a[i*2]);
        else if (a[i*2]==-1)
            tot+=2,v.pb(a[i*2-1]);
    }
    For(i,1,n*2)
        if (!b[i])
            v.pb(i);
    sort(v.begin(),v.end());
    v.pb(0);
    reverse(v.begin(),v.end());
    dp[0][0][0]=1;
    For(i,1,tot)
        For(j,0,tot)
            For(k,0,tot){
                int val=dp[i-1][j][k];
                if (!val)
                    continue;
                if (!b[v[i]]){
                    Add(dp[i][j+1][k],val);
                    if (j>0)
                        Add(dp[i][j-1][k],val);
                    if (k>0)
                        Add(dp[i][j][k-1],(LL)val*k%mod);
                }
                else {
                    Add(dp[i][j][k+1],val);
                    if (j>0)
                        Add(dp[i][j-1][k],val);
                }
            }
    int ans=dp[tot][0][0];
    For(i,1,cnt)
        ans=(LL)ans*i%mod;
    cout<<ans<<endl;
    return 0;
}

原文地址:https://www.cnblogs.com/zhouzhendong/p/AGC031F.html

时间: 2024-10-31 03:13:57

AtCoder Grand Contest 031 (AGC031) F - Permutation and Minimum 动态规划的相关文章

Atcoder Grand Contest 026 (AGC026) F - Manju Game 博弈,动态规划

原文链接www.cnblogs.com/zhouzhendong/AGC026F.html 前言 太久没有发博客了,前来水一发. 题解 不妨设先手是 A,后手是 B.定义 \(i\) 为奇数时,\(a_i\) 为"奇数位上的数":\(i\) 为偶数时, \(a_i\) 为"偶数位上的数".定义左.右两端的数分别表示 \(a_1\) 和 \(a_n\). 考虑第一步: 首先,如果 A 取了左右某一个端点,那么他必然能取走和他取的点奇偶性相同的所有点. 然后,我们考虑

AtCoder Grand Contest 031 B - Reversi(DP)

B - Reversi 题目链接:https://atcoder.jp/contests/agc031/tasks/agc031_b 题意: 给出n个数,然后现在你可以对一段区间修改成相同的值,前提是左右端点的值相同.问最后这n个数有多少种不同的值. 题解: 设dp[i]表示只考虑1~i这段,有多少不同的值.然后对于当前第i位,有两种选择,修改或者不修改,不修改的话就是dp[i-1]:修改的话就是dp[k],这里k表示上一个相同颜色的位置. 注意一下如果i-1和i的颜色相同,当前要跳过,这个时候

AtCoder Grand Contest 031(UPC个人训练赛第十五场)

传送门: [1]:AtCoder [2]:UPC 参考资料 [1]:https://www.cnblogs.com/QLU-ACM/p/11191644.html B.Reversi(记录结果再利用的DP) •题意 有 n 个石子,编号为 1~n ,第 i 个石子被涂成颜色 coli: 操作:任选两个颜色相同的石子 i,j ,i 与 j 之间的所有石子涂成颜色 coli: 上述操作可以不执行,也可以执行多次: 求最多有多少不同的颜色序列: •题解 定义 dp[ i ] 前 i 个石子最多的不同的

AtCoder Grand Contest 002 (AGC002) F - Leftmost Ball 动态规划 排列组合

原文链接https://www.cnblogs.com/zhouzhendong/p/AGC002F.html 题目传送门 - AGC002F 题意 给定 $n,k$ ,表示有 $n\times k$ 个球,其中,颜色为 $1,2,\cdots, n$ 的球各有 $k$ 个. 将这些球任意排列成一排,对于每一种颜色,将这种颜色的球的最左边的那个涂成颜色 $0$ . 问最终可以得到多少种不同的排列. $1\leq n,k\leq 2000,{\rm Mod} = 10^9 +7$ 题解 首先当 $

AtCoder Grand Contest 026 (AGC026) E - Synchronized Subsequence 贪心 动态规划

原文链接 题目传送门 - AGC026E 题意 给定一个长度为 $2n$ 的字符串,包含 $n$ 个 $'a'$ 和 $n$ 个 $'b'$ . 现在,让你按照原顺序取出一些字符,按照原顺序组成新的字符串,输出所有满足条件的字符串中字典序最大的?(字典序: $b>a>""$) 条件限制:当且仅当取了原序列的第 $i$ 个 $'a'$ 时,原序列的第 $i$ 个 $'b'$ 也被取了. $n\leq 3000$ 题解 代码 #include <bits/stdc++.h

AtCoder Grand Contest 025 Problem D

www.cnblogs.com/shaokele/ AtCoder Grand Contest 025 Problem D Time Limit: 2 Sec Memory Limit: 1024 MB Description Takahashi is doing a research on sets of points in a plane. Takahashi thinks a set \(S\) of points in a coordinate plane is a good set w

AtCoder Grand Contest 024 Problem E(动态规划)

www.cnblogs.com/shaokele/ AtCoder Grand Contest 024 Problem E Time Limit: 2 Sec Memory Limit: 1024 MB Description Find the number of the possible tuples of sequences (\(A_0,A_1,-,A_N\)) that satisfy all of the following conditions, modulo \(M\): ? Fo

AtCoder Grand Contest 011

AtCoder Grand Contest 011 upd:这篇咕了好久,前面几题是三周以前写的... AtCoder Grand Contest 011 A - Airport Bus 翻译 有\(n\)个乘客到达了飞机场,现在他们都要坐车离开机场.第\(i\)个乘客到达的时间是\(T_i\),一个乘客必须在\([T_i,T_i+k]\)时刻做到车,否则他会生气.一辆车最多可以坐\(C\)个人.问最少安排几辆车可以让所有人都不生气. 题解 从前往后贪心即可. #include<iostream

AtCoder Grand Contest 014

AtCoder Grand Contest 014 A - Cookie Exchanges 有三个人,分别有\(A,B,C\)块饼干,每次每个人都会把自己的饼干分成相等的两份然后给其他两个人.当其中有一个人的饼干数量是奇数的时候停止,求会进行几次这样子的操作,或者会永远进行下去. 首先无解的情况一定是三个数都是相等的偶数. 否则直接暴力模拟就行了.(盲猜答案不会很大) 证明一下答案的范围:不妨令\(A\le B\le C\),那么最大值和最小值之间的差就是\(C-A\),那么执行完一次操作之后