cf285 D. Permutation Sum 状压 dfs打表

题意:

如果有2个排列a,b,定义序列c为:

c[i] = (a[i] + b[i] - 2) % n + 1

但是,明显c不一定是一个排列

现在,给出排列的长度n (1 <= n <= 16)

问有多少种a,b的排列的组合的方案,使得得到的c也是一个排列

排列的组合a = x,b = y 与 排列的组合a = y,b = x算是2种方案

思路:

有3个排列,不妨假设排列a 为1,2,3,...,n

这样结果再 * n! 就是答案

考虑状压dp

j是一个16位的数,记录b的n个数被用了哪些数

f(i,j)表示a用了1~i,b用了j记录的那些数,产生的c的前i个的方案数

init : f(0,0) = 1

ans = f(n,(1<<n)-1) * n!转移方程:

没法转移阿,因为我们还必须知道c哪些数用了,哪些数没有用

如果再加一维记录c的状态的话,数组开不下了

那就写成搜索的形式了

dfs(u,v,w) 表示a用了1~u,b,c分别用了v,w记录的那些数

if(u == n + 1)  ans++;

但是这样会超时啊,1 <= n <= 16,这么小,那就直接打表了

代码:

  //File Name: cf285D.cpp
  //Author: long
  //Mail: [email protected]
  //Created Time: 2016年07月09日 星期六 16时44分05秒

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>

#define LL long long

using namespace std;

const int MOD = (int)1e9 + 7;

LL ans,n;
LL jie[17];
int res[17] = {0,1,0,18,0,1800,0,670320,0,734832000,0,890786230,0,695720788,0,150347555,0};

void init(){
    jie[0] = 1;
    for(int i=1;i<17;i++)
        jie[i] = i * jie[i-1] % MOD;
    //ans = 0;
    //dfs(1,0,0);
}

void dfs(int a,int b,int c){
    if(a == n + 1){
        ans++;
        if(ans >= MOD)
            ans -= MOD;
        return ;
    }
    int v;
    for(int i=0;i<n;i++){
        if(((1<<i) & b) == 0){
            v = (i + a - 1) % n;
            if(((1<<v) & c) == 0)
                dfs(a+1,b|(1<<i),c|(1<<v));
        }
    }
}

int main(){
    init();
    while(~scanf("%d",&n)){
        printf("%d\n",res[n]);
    }
    return 0;
}
时间: 2024-09-26 20:09:25

cf285 D. Permutation Sum 状压 dfs打表的相关文章

POJ 2411 Mondriaan&#39;s Dream (状压+dfs)

Language: Default Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 12405   Accepted: 7239 Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in

2018icpc南京网络赛-E AC Challenge(状压+dfs)

题意: n道题,每道题有ai和bi,完成这道题需要先完成若干道题,完成这道题可以得到分数t*ai+bi,其中t是时间 1s, n<=20 思路: 由n的范围状压,状态最多1e6 然后dfs,注意代码中dfs里的剪枝, 对一个状态statu,因为贪心的取最大值就行,所以及时剪枝 代码: 当时写不出来真是菜的活该 #include<iostream> #include<cstdio> #include<algorithm> #include<cmath>

HDU 4770 DFS&amp;状压

一个n*m的房间有的房间是可破坏的,其他不可破坏,现在给你一些L型的灯,其中只有一个可以旋转,其他不能,让你用最少的灯覆盖所有的可破坏区域,且不能覆盖不可破坏的区域. 枚举旋转的灯,对剩下的DFS即可,状压存储已经被点亮的灯 #include "stdio.h" #include "string.h" struct P { int x,y; }p[21]; int ans,n,m,cnt,aim,b[21]; char str[210][210]; int judg

HDU Untitled(状压DP OR dfs枚举子集)

Untitled Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 325    Accepted Submission(s): 169 Problem Description There is an integer a and n integers b1,-,bn. After selecting some numbers from b

poj2411--Mondriaan&#39;s Dream(状压dp+dfs)

Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 12315   Accepted: 7189 Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series

LA UVaLive 6625 Diagrams &amp; Tableaux (状压DP 或者 DFS暴力)

题意:给一个的格子图,有 n 行单元格,每行有a[i]个格子,要求往格子中填1~m的数字,要求每个数字大于等于左边的数字,大于上边的数字,问有多少种填充方法. 析:感觉像个DP,但是不会啊...就想暴力试试,反正数据量看起来不大才7,但是...TLE了,又换了一个暴力方法,2秒多过了,差点啊. 其实这是一个状压DP,dp[i][s]表示在第 i 列,在集合 s 中有方法数,那么怎么转移呢,这个还是挺简单的,就是判断第i+1列是不是比第 i 列都大于等于就ok了, 输入时先把行,转化成列,再计算,

[状压DP][DFS]JZOJ 2679 跨时代

Description 钟逆时针而绕,恶物狰狞的倾巢,我谦卑安静地于城堡下的晚祷,压抑远古流窜的蛮荒暗号,而管风琴键高傲的说,那只是在徒劳.我的乐器在环绕,时代无法淘汰我霸气的皇朝. 你无法预言,因为我越险,翅越艳:没有句点,跨时代蔓延,翼朝天. 月下浮雕,魔鬼的浅笑,狼迎风嚎,蝠翔似黑潮,用孤独去调尊严的色调.我跨越过世代,如兽般的姿态,琴声唤起沉睡的血脉.不需要被崇拜,如兽般的悲哀,只为永恒的乐曲存在,醒过来. 去年万众瞩目的<跨时代>专辑发行之后,周杰伦又开始了他的世界巡回演唱会<

HDU-3811 Permutation 状压DP

题意:求满足下面条件的n的排列个数:条件为给出m个点对<x,y> 只要这个排列满足至少一个位置p[x]=y即算满足条件. 解法:这道题不算难应该要想出来的,结果没想出来自己还是蒟蒻呀qwq.我们观察满足一个p[x]=y即可以,但是这样很难统计,发现它的反面条件就是不满足任何一个p[x]=y.于是我们从这个入手用状压DP求出不满足条件数量然后用总数n!减去即是答案. 设dp[i][state]代表长度为i的排列使用数字情况state的不完美数量 用填表法DP,写出状态转移方程  dp[i+1][

URAL 1326. Bottle Taps(简单的状压dp)

题目不太好读懂,就是先给你一个n代表要从n个物品中买东西,然后告诉你这n个东西的单价,在给你m个集合的情况,就是每个结合中有x件物品,他们合起来买的价格是k.这x件物品依次是:p1--px.之后给你一个kk,表示你要买的物品的编号.让你求出来如何花费最少的钱买到要求的序列. 20,可以状压啊,注意一开始的时候先把单价的状态处理出来...之后就是水题了啊. 1326. Bottle Taps Time limit: 3.0 second Memory limit: 64 MB Programmer