其实看到这个题,我第一时间想到的是深搜,不过有这句“输出答案mod 1000000007便可”就基本肯定不是深搜了。ios
第一次咱们选择第一个序列的某一个,第二次选择就减小了一次选择机会,只能选择除了选过的之外的了,第三次选择又少了一次,第四次又少了一次......spa
那么不难想到:第一个*第二个-1*第三个-2*第四个-3......code
这样咱们稍微画画图就能够得出公式:ans*=(m[i]-sum);blog
sum是每次应该减小的次数(每次++),m[i]是目前的这个序列一共有多少个数。排序
代码以下:it
#include<iostream> #include<cstdio> using namespace std; unsigned long long n,m[10010],ans=1,sum=0; int main(){ scanf("%u",&n); for(int i=0;i<n;i++){ scanf("%u",&m[i]); } for(int i=0;i<n;i++){//遍历一遍 ans*=(m[i]-sum)%1000000007;//公式 sum++;//减小的次数 } printf("%u\n",ans); return 0; }
可是这样咱们会发现,当碰到5 1 2 3 2 1这样的数的时候就会over(由于2<那时候的sum,就会获得一个负数)。io
那要不咱们加个特判:if(m [i]>=sum)的时候才让他执行上面的那个语句?class
#include<iostream> #include<cstdio> using namespace std; unsigned long long n,m[1010],ans=1,sum=0; int main(){ scanf("%u",&n); for(int i=0;i<n;i++){ scanf("%u",&m[i]); } for(int i=0;i<n;i++){//遍历 if(m[i]>=sum){//特判,若是m[i]>=sum才能执行下面的语句。 ans*=(m[i]-sum); } else{//不然就直接让ans=0 ans=0; break; } ans%=1000000007; sum++;//减小的次数 } printf("%u\n",ans); return 0; }
但是碰到5 4 5 6 2 1就又难办了(由于这样虽然会获得负数,可是仍是会有不少种选编号方法的)。stream
那该怎么办??遍历
咱们的救星来了!他就是——sort,只要用sort排一边序就行了。
若是不排序,咱们就不知道前一个选择的号码是否是在如今这个m[i]里面,就会发生前面的状况。
AC代码以下:
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; unsigned long long n,m[1010],ans=1,sum=0;//开大点总没坏处 int main(){ scanf("%u",&n); for(int i=0;i<n;i++){ scanf("%u",&m[i]); } sort(m,m+n);//排序一遍,若是不排序,咱们就不知道前一个选择的号码是否是在如今这个m[i]里面,就会发生前面的状况。 for(int i=0;i<n;i++){ ans*=(m[i]-sum); ans%=1000000007;//千万不要忘了这个,若是数大了,不加这个就会over sum++; } printf("%u\n",ans); return 0; }