[hdu5399 Too Simple]YY

题意:m个{1,2...n}→{1,2...,n}的函数,有些已知有些未知,求对任意i∈{1,2,...,n},f1(f2(...(fm(i)))=i的方案总数,为了方便简记为F(i)

思路:如果存在一个f,当i!=j时,有f(i)=f(j),那么方案数为0,因为由里到外进行f运算,两个不同的数到这里来了变成了i和j,然后变成了同一个数,最终还是等于同一个数,所以在最外面至少有一个不会满足F(x)=x。如果f全部确定了,那么只需对每个i计算一下F(i)即可确定答案。如果f没确定的个数为cnt,则答案就是n!cnt-1,因为对后(cnt-1)个未确定的f,对于它们的每种合法情况,第一个f有且仅有唯一一种情况使得F(i)=i成立。

#pragma comment(linker, "/STACK:10240000")
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define X                   first
#define Y                   second
#define pb                  push_back
#define mp                  make_pair
#define all(a)              (a).begin(), (a).end()
#define fillchar(a, x)      memset(a, x, sizeof(a))
#define copy(a, b)          memcpy(a, b, sizeof(a))

typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull;

//#ifndef ONLINE_JUDGE
void RI(vector<int>&a,int n){a.resize(n);for(int i=0;i<n;i++)scanf("%d",&a[i]);}
void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>
void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?1:-1;
while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>
void print(const T t){cout<<t<<endl;}template<typename F,typename...R>
void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>
void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}
//#endif
template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);}
template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);}

const double PI = acos(-1.0);
const int INF = 1e9 + 7;
const double EPS = 1e-12;

/* -------------------------------------------------------------------------------- */

const int md = 1e9 + 7;

int n, m, f[101][101], fac[105];

int powermod(int a, int n, int md) {
    int ans = 1, tmp = a;
    while (n) {
        if (n & 1) ans = (ll)ans * tmp % md;
        tmp = (ll)tmp * tmp % md;
        n >>= 1;
    }
    return ans;
}

bool chk() {
    for (int i = 1; i <= n; i ++) {
        int p = i;
        for (int j = m - 1; j >= 0; j --) {
            p = f[j][p];
        }
        if (p != i) return false;
    }
    return true;
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGE
    fac[0] = 1;
    for (int i = 1; i <= 100; i ++) fac[i] = (ll)fac[i - 1] * i % md;
    int x;
    while (cin >> n >> m) {
        int cnt = 0;
        bool ok = true;
        for (int i = 0; i < m; i ++) {
            scanf("%d", &x);
            if (x == - 1) cnt ++;
            else {
                bool vis[105] = {};
                vis[x] = true;
                f[i][1] = x;
                for (int j = 1; j < n; j ++) {
                    scanf("%d", &x);
                    vis[x] = true;
                    f[i][j + 1] = x;
                }
                for (int i = 1; i <= n; i ++) {
                    if (!vis[i]) ok = false;
                }
            }
        }
        if (!ok) puts("0");
        else {
            if (cnt) printf("%d\n", powermod(fac[n], cnt - 1, md));
            else printf("%d\n", chk());
        }
    }
    return 0;
}
时间: 2024-12-20 04:43:55

[hdu5399 Too Simple]YY的相关文章

hdu5399(2015多校9)--Too Simple

题目链接:点击打开链接 题目大意:有m个映射,从1到n映射到1到n,记为f1,f2,f3,,,fm,并且这些映射满足f1( f2( f3(,,,,fm(i) ) ) ) = i现在已知几个映射的值,还有几个映射是不知道的,问不知道的映射一共有几种可能的组合方式. 输入n m,之后m行,如果一行的第一个数为-1,代表这一个映射fi是不知道的,否则一行有n个数,第i行的第j个数字x代表fi(j) = x 问最终的种类(对1e9+7取余) 1.如果映射不是单射,也就是存在fi(x) = fi(y)并且

HDU5399——贪心——Too Simple

http://acm.hdu.edu.cn/showproblem.php?pid=5399 /* 先特判有重复数的情况,如果有就输出-1 如果全是数字那么就判是否符合条件 剩下的就是m!的(cout-1)次 */ /************************************************ * Author :Powatr * Created Time :2015-8-18 18:40:18 * File Name :1004.cpp ******************

HDU 4781 Assignment For Princess(YY乱搞)

http://acm.hdu.edu.cn/showproblem.php?pid=4781 Assignment For Princess Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 639    Accepted Submission(s): 196 Special Judge Problem Description Long

hdu_5794_A Simple Chess(lucas+dp)

题目链接:hdu_5794_A Simple Chess 题意: 给你n,m,从(1,1)到(n,m),每次只能从左上到右下走日字路线,有k(<=100)的不能走的位置,问你有多少方案 题解: 画图可看到路线是一个杨辉三角的图,然后我们可以将对应的x,y转换到对应的点上,也可以吧杨辉三角看成一个平行四边形, 我这里看成的平行四边形,设dp[i]为从起点到第i个障碍物的的方案数,那么dp[i]=dp[i]-sum(dp[j](第j个点能走到i这个点)*(j到i的方案数)). 然后我们把终点放到最后

[Linux-vi] The simple set of vi command

Source : https://www.cs.colostate.edu/helpdocs/vi.html What is vi? The default editor that comes with the UNIX operating system is called vi (visual editor). [Alternate editors for UNIX environments include pico and emacs, a product of GNU.]The UNIX

ural 2003. Simple Magic 数论 因数分解

2003. Simple Magic Time limit: 1.0 second Memory limit: 64 MB Do you think that magic is simple? That some hand-waving and muttering incomprehensible blubber is enough to conjure wonderful gardens or a fireball to burn your enemies to ashes? The real

「题解」:Simple

问题 A: Simple 时间限制: 1 Sec  内存限制: 256 MB 题面 题面谢绝公开. 题解 不算数学的数学题?? 直接枚举会重.$60%$两种算法:1.无脑$vis$数组记录.2.$exgcd$解方程判定是否有解. $100%$:首先考虑特殊情况:$n$.$m$互质. 我们设$n*x+m*y=z$,考虑枚举$y$和$x$,不难发现,当$y>=x$的时候均能找到一个$y'$使得$n|(y-y')$. 于是会出现重复.因此只需枚举$y([0,n-1])$,计算贡献即可. 对于一般情况,

初译 Support Vector Machines:A Simple Tutorial(一)

从本次开始我将开始尝试着逐章翻译一下 Alexey Nefedov的<Support Vector Machines:A Simple Tutorial>这本教材,这可是我们导师极力推荐的SVM教材,看了好久一直感觉一脸懵逼,索性开坑翻译一下吧,也当是加深理解,毕竟我也是一知半解,如果翻译的有不对的地方还望大佬们斧正,欢迎提意见,欢迎讨论. 嗯,就是这样. (一)Introduction 在本章节中将会介绍一些用于定义支持向量机(SVM)的基础的概念,这些概念对于理解SVM至关重要,假定读者了

ubuntu16.04下安装NS-2.35以及对simple例的理解

本人是在VMWare上安装的ubuntu16.04版本,然后安装NS2.35. 1.下载ns2的安装包,这里我选择的是ns-allinone-2.35.tar.gz压缩格式的all in one安装包,all in one 安装包包含所有的组件,比较方便,另附下载地址: http://www.isi.edu/nsnam/ns/ns-build.html 2.安装前要先进行一些准备工作进行配置环境,输入如下代码: $sudo apt-get install build-essential $sud