zoukankan      html  css  js  c++  java
  • P1866 编号

    摘要:太郎有N只兔子,现在为了方便识别它们,太郎要给他们编号。兔子们向太郎表达了它们对号码的喜好,每个兔子i想要一个整数,介于1和Maxnumber[i]之间(包括1和Maxnumber[i])。当然,每个兔子的编号是不同的。现在太郎想知道一共有多少种编号的方法。你只用输出答案mod 1000000007即可。如果这是不可能的,就输出0。

    其实看到这个题,我第一时间想到的是深搜,不过有这句“输出答案mod 1000000007即可”就基本确定不是深搜了。

    于是我就换个思路想了想:

    第一次我们选择第一个序列的某一个,第二次选择就减少了一次选择机会,只能选择除了选过的以外的了,第三次选择又少了一次,第四次又少了一次......

    那么不难想到:第一个*第二个-1*第三个-2*第四个-3......

    这样我们稍微画画图就可以得出公式:ans*=(m[i]-sum);

    sum是每次应该减少的次数(每次++),m[i]是目前的这个序列一共有多少个数。

    代码如下:

    #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,就会得到一个负数)。

    那要不我们加个特判:if(m [i]>=sum)的时候才让他执行上面的那个语句?

    #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就又难办了(因为这样虽然会得到负数,但是还是会有很多种选编号方法的)。

    那该怎么办??

    我们的救星来了!他就是——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;
    }

    以上就是我这道题的全部思路,如果有什么不对的地方,还请各位大佬及时向我纠正。

  • 相关阅读:
    yii 引入文件
    CodeForces 621C Wet Shark and Flowers
    面试题题解
    POJ 2251 Dungeon Master
    HDU 5935 Car(模拟)
    HDU 5938 Four Operations(暴力枚举)
    CodeForces 722C Destroying Array(并查集)
    HDU 5547 Sudoku(dfs)
    HDU 5583 Kingdom of Black and White(模拟)
    HDU 5512 Pagodas(等差数列)
  • 原文地址:https://www.cnblogs.com/dgdger/p/12849156.html
Copyright © 2011-2022 走看看