HDU 5399(Too Simple-判定映射)

Too Simple

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1035    Accepted Submission(s): 353


Problem Description
Rhason Cheung had a simple problem, and asked Teacher Mai for help. But Teacher Mai thought this problem was too simple, sometimes naive. So she ask you for help.

Teacher Mai has m functions f1,f2,,fm:{1,2,,n}{1,2,,n} (that means for all x{1,2,,n},f(x){1,2,,n} ). But Rhason only knows some of these functions, and others are unknown.

She wants to know how many different function series f1,f2,,fm there are that for every i(1in) , f1(f2(fm(i)))=i . Two function series f1,f2,,fm and g1,g2,,gm are considered different if and only if there exist i(1im),j(1jn) , fi(j)gi(j) .
 

Input
For each test case, the first lines contains two numbers n,m(1n,m100) .

The following are m lines. In i -th line, there is one number 1 or n space-separated numbers.

If there is only one number 1 , the function fi is unknown. Otherwise the j -th number in the i -th line means fi(j) .
 

Output
For each test case print the answer modulo 109+7 .
 

Sample Input
  
  
3 3 1 2 3 -1 3 2 1
 

Sample Output
  
  
1
Hint
The order in the function series is determined. What she can do is to assign the values to the unknown functions.
 

Author
xudyh
 

Source
 

Recommend
wange2014   |   We have carefully selected several similar problems for you:   5421  5420  5419  5418  5417 
 

已知函数有一个不是双射,必定无解

若所有函数均已知,直接判断

否则,只要有一个 -1, 那么必能构造出解

有k个-1,前k-1个随便排 ,最后那个就能推出 ans=(n!)^(k-1)




#include<bits/stdc++.h> 
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])  
#define Lson (x<<1)
#define Rson ((x<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (1000000007)
#define MAXN (100+10)

typedef long long ll;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int n,m;
bool b[MAXN];
int f[MAXN][MAXN];
int g[MAXN];
int main()
{
//	freopen("D.in","r",stdin);
	
	while(cin>>n>>m) {
		int cnt=0; bool flag=0;
		For(i,m)
		{
			MEM(b)
			int p;
			scanf("%d",&p);
			if (p==-1) { ++cnt;continue;}
			else f[i][1]=p;
			b[p]=1;
			Fork(j,2,n) {
				scanf("%d",&p);f[i][j]=p;
				if (!b[p]) b[p]=1; else flag=1;
			}
		}
		
		if (flag) {
			puts("0");continue;
		}	
		
		if (!cnt) {
			For(i,n) g[i]=i;
			ForD(i,m) 
				For(j,n) g[j]=f[i][g[j]];
			bool flag=0;
			For(i,n) if (g[i]^i) flag=1;
			if (flag) puts("0");else puts("1");
			continue;
		}
		
		if (cnt==1)
		{
			puts("1");
			continue;
		}
		
		ll ans=1,p2=1;
		For(i,n) p2=mul(p2,i);
		For(i,cnt-1) ans=mul(p2,ans);
		cout<<ans<<endl;
		
		
	}	
	
	return 0;
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值