题目描述
太郎有N只兔子,现在为了方便识别它们,太郎要给他们编号。兔子们向太郎表达了它们对号码的喜好,每个兔子i想要一个整数,介于1和Maxnumber[i]之间(包括1和Maxnumber[i])。当然,每个兔子的编号是不同的。现在太郎想知道一共有多少种编号的方法。
你只用输出答案mod 1000000007即可。如果这是不可能的,就输出0.
输入输出格式
输入格式:
第一行是一个整数N。(1≤N≤50)
第二行N个整数Maxnumber[i]。(1≤Maxnumber[i]≤1000)
输出格式:
一个整数
输入输出样例
输入样例#1
2 5 8
输出样例#1
35
思路
设n=3,3个数分别为6,12,8。
则先升向排序6,8,12。
第一个号码有6种选择
第二个号码有8-1=7(种)选择(去掉1种)
第三个号码有12-2=10(种)选择(去掉2种)
结果为6*7*10=420。由于结果可能很大,mod 1000000007。
#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
long long int n,a[51]={},i,j,s(1);//开大点
cin>>n;
for(i=1;i<=n;i++)
{
cin>>a[i];
}
sort(a+1,a+n+1);
for(i=1;i<=n;i++)
{
s=s*(a[i]-i+1);
s=s%1000000007;
}
cout<<s<<endl;
return 0;
}
还有一种dfs的写法,类似于上面的数学推论,但是我写的只有30分,仅供借鉴。
#include <stdio.h>
#include <iostream>
int n,s,a[61],b[61];
using namespace std;
void dfs(int i)//当前是第i层
{
register int j;
if(i==n+1)//类似于全排列的写法
{
s++;
s=s%1000000007;
return;
}
for(j=1;j<=a[i];j++)//搜索算符
{
if(b[j]==0)//如果没搜索过
{
b[j]=1;//标记搜索过了
dfs(i+1);//搜索下一层
b[j]=0;//取消标记
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int i;
cin>>n;
for(i=1;i<=n;i++)
{
cin>>a[i];
}
dfs(1);
cout<<s<<endl;
return 0;
}