zoukankan      html  css  js  c++  java
  • [JLOI2013]地形生成

    题目描述

    最近IK正在做关于地形建模的工作。其中一个工作阶段就是把一些山排列成一行。每座山都有各不相同的标号和高度。为了遵从一些设计上的要求,每座山都设置了一个关键数字,要求对于每座山,比它高且排列在它前面的其它山的数目必须少于它的关键数字。 显然满足要求的排列会有很多个。

    对于每一个可能的排列,IK生成一个对应的标号序列和等高线序列。标号序列就是按顺序写下每座山的标号。

    等高线序列就是按顺序写下它们的高度。例如有两座山,这两座山的一个合法排列的第一座山的标号和高度为1和3,而第二座山的标号和高度分别为2和4,那么这个排列的标号序列就是1 2,而等高线序列就是3 4.

    现在问题就是,给出所有山的信息,IK希望知道一共有多少种不同的符合条件的标号序列和等高线序列。

    输入输出格式

    输入格式:

    输入第一行给出山的个数N。接下来N行每行有两个整数,按照标号从1到N的顺序分别给出一座山的高度和关键数 

    输出格式:

    输出两个用空格分隔开的数,第一个数是不同的标号序列的个数,第二个数是不同的等高线序列的个数。这两个答案都应该对2011取模,即输出两个答案除以2011取余数的结果

    输入输出样例

    输入样例#1:
    2
    1 2
    2 2
    输出样例#1:
    2 2

    说明

    对于所有的数据,有1<=N<=1000,所有的数字都是不大于109的正整数。

    首先,考虑第一问:满足条件的编号条件

    我们发现高度较小的山对高度较大的山是没有影响的

    从大到小排序,这样i就只能放在1~min(i-1,k[i])

    又考虑可以排在相同的后面

    假设i~j相同,对于每一个j

    ans1*=(min(i-1,k[i])+j-i+1)

    第二问就是说满足条件的高度排列,即存在重复

    可以这样想,f[i][k]前i个相同高度排在前k的方案

    f[i][j]=f[i-1][j]+f[i-1][j-1]+f[i-1][j-2]+……+f[i-1][1]  (1<=j<=b[i])
    f[i][j]=f[i-1][j]+f[i][j-1]

    转化为
    f[i]+=f[i-1] (1<=i<=b[i])

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 using namespace std;
     6 struct M
     7 {
     8     int h,k;
     9 }a[10001];
    10 int n;
    11 int ans1=1,ans2=1,f[10001];
    12 bool cmp(M x,M y)
    13 {
    14     return (x.h>y.h||(x.h==y.h&&x.k<y.k));
    15 }
    16 int main()
    17 {int i,j,k,pos;
    18     cin>>n;
    19     for (i=1;i<=n;i++)
    20     {
    21      scanf("%d%d",&a[i].h,&a[i].k);
    22      a[i].k--;
    23     }
    24      sort(a+1,a+n+1,cmp);
    25      pos=1;
    26       for (i=1;i<=n;i=pos+1)
    27       {
    28          pos=i;
    29           while (a[pos].h==a[pos+1].h&&pos<n) pos++;
    30           memset(f,0,sizeof(f));
    31           f[0]=1;
    32           for (j=i;j<=pos;j++)
    33           {
    34             ans1*=min(a[j].k,i-1)+j-i+1;
    35             ans1%=2011;
    36              for (k=1;k<=min(a[j].k,i-1);k++)
    37              {
    38                 f[k]+=f[k-1];
    39                 f[k]%=2011;
    40              }
    41           }
    42           int sum=0;
    43           for (k=0;k<=i-1,k<=a[pos].k;k++)
    44             sum+=f[k],sum%=2011;
    45         ans2*=sum;
    46         ans2%=2011;
    47       }
    48 cout<<ans1<<' '<<ans2<<endl;
    49 }
  • 相关阅读:
    自动生成A~Z的按字母查询可以用到(不用一一去写A.B.C……Z)
    GridView导出Excel
    简单的遮罩层弹出框(弹出一个表单,里面包含验证码,验证码正确方可提交)
    根据IP地址返回IP的详细信息(Web Service)
    九方格游戏的代码(此逻辑算法适用于任意方格数)
    for循环的变量设置
    注意TextField文本宽高
    两个重叠显示对象的层级调整(第二种方法时候来补充的
    用数组来存储显示对象
    DisplayObjectContainer的getChildAt()方法
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7401667.html
Copyright © 2011-2022 走看看