• 神奇的Noip模拟试题一试 2 排队


    2 排队

    (lineup.pas/.c/.cpp)

    【问题描述】

          小sin所在的班有n名同学,正准备排成一列纵队,但他们不想按身高从矮到高排,那样太单调,太没个性。他们希望恰好有k对同学是高的在前,矮的在后,其余都是矮的在前,高的在后。如当n=5,k=3时,假设5人从矮到高分别标为1、2、3、4、5,则(1,5,2,3,4)、(2,3,1,5,4)、(3,1,4,2,5)都是可行的排法。小sin想知道总共有多少种可行排法。

    【输入】

          输入文件名为lineup.in。

          一行两个整数n和k,意义见问题描述。

    【输出】

          输出文件名为lineup.out。

          输出一个整数,表示可行排法数。由于结果可能很大,请输出排法数mod 1799999的值。

    【输入输出样例】

    lineup.in

    lineup.out

    5 3

    15

    【数据范围】

          对于20%的数据,有n≤10,k≤40;

          对于60%的数据,有n≤100,k≤500;

          对于100%的数据,有n≤100,k≤n*(n-1)/2。

    解题报告

      像这样的题,也正如这套题一样的完全是思考的时间多。(哎,说得好像我做出来了一样,但其实我连样例都没有去想“天,15个,算了不想了。”所以啊,还是要有耐心,考场上一定要静下来,不要急躁,有同学用了两个小时找规律,最终不负有心人,全过了。)

      首先,我们需要找规律,而找规律不是随机就找到了,需要观察和对比两组甚至多组数据。于是,打开打表模式:

    nk  0   1   2   3   4   5   6   

    1     1   0   0   0   0   0   0

    2     1   1   0   0   0   0   0

    3     1   2   2   1   0   0   0

    4     1   3   5   6   5   3   1

    5     1   4   9  15  20 22 20 .......

       每一个n都有一个k的数量的限制,即长度 l ,如果k>l 就为0 ,l =0,1,3,6,等等。l+=i-1;  每一次都是在上一次的基础上添一个比上一次最大值大1的数,如下:

    上一次:1 2 3 4 5

    这一次添一个6 有6 种添法:在5后,在4~5间,在3~4间,在2~3间,在1~2间,在1前;

    分别有6种增加的可能性:    不影响,多一组,  多两组,   多三组,   多四组,    多五组

      因此可以列出方程:f[i][j]( i 个数,取 j 组)=f[i-1][j]+f[i-1][j-1]+...+f[i-1][j-i+1]

                      (转换):f[i][j-1]=f[i-1][j-1]+f[i-1][j-2]+...+f[i-1][j-i]

                   (二式相减):f[i][j]=f[i][j-1]+f[i-1][j]-f[i-1][j-i]

      方程有了,代码就简单多了。

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 int n,k;
     5 int f[105][5005];
     6 const int inf=1799999;
     7 int main()
     8 {
     9     freopen("lineup.in","r",stdin);
    10     freopen("lineup.out","w",stdout);
    11     cin>>n>>k;
    12     int l=0;
    13     for (int i=1;i<=n;i++)
    14     {
    15         l+=i-1;
    16         f[i][0]=1;
    17         for (int j=1;j<=k;j++)
    18         {
    19             if (j>l) break;
    20                 f[i][j]=(f[i-1][j]+f[i][j-1])%inf;
    21             if (j-i>=0) f[i][j]=(f[i][j]-f[i-1][j-i]+inf)%inf;
    22         }
    23     }
    24     cout<<f[n][k];
    25     return 0;
    26 }
  • 相关阅读:
    时间工厂[XDU1013]
    奇妙的旅行[XDU1012]
    金子上的友情[XDU1011]
    素数环问题[XDU1010]
    转盘游戏[XDU1006]
    跳舞毯[XDU1005]
    Tri Tiling[HDU1143]
    A Walk Through the Forest[HDU1142]
    核反应堆[HDU2085]
    How Many Trees?[HDU1130]
  • 原文地址:https://www.cnblogs.com/lx0319/p/5679293.html
Copyright © 2020-2023  润新知