其實看到這個題,我第一時間想到的是深搜,不過有這句「輸出答案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; }