清橙 A1210. 光棱坦克

Posted Soda

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了清橙 A1210. 光棱坦克相关的知识,希望对你有一定的参考价值。

A1210. 光棱坦克
时间限制:1.0s   内存限制:512.0MB  
总提交次数:   AC次数:   平均分:
 
将本题分享到:
      
   
试题来源
  2010中国国家集训队命题答辩
问题描述
  一个平面直角坐标系上,有N个点,标号为1到N,其中第i个点的坐标为(x[i], y[i])。
  求满足以下两个条件的点列{p[i]}的数目(假设{p[i]}的长度为M):
  1) 对任意1 <= i < j <= M,必有y[p[i]] > y[p[j]];
  2) 对任意3 <= i <= M,必有x[p[i-1]] < x[p[i]] < x[p[i-2]]或者x[p[i-2]] < x[p[i]] < x[p[i-1]]。
  求满足条件的非空序列{p[i]}的数目,结果对一个整数Q取模。
输入格式
  第1行是两个由空格隔开的整数:N和Q。
  第2行到第N+1行,每行有两个整数。其中的第i行的两个整数分别是x[i]和y[i]。
输出格式
  输出文件只有一行,包含一个整数,表示序列{p[i]}的数目对Q取模的结果。
样例输入
4 100
2 2
3 1
1 4
4 3
样例输出
14
样例说明
  一共4个点,位置如下:
技术分享图片

  如果M=4, 那么只有1种序列符合要求,如下图所示:

技术分享图片
  如果M = 3,那么有3种序列符合要求,如下图:

技术分享图片
  如果M = 2,那么有6种序列符合要求,如下图:
技术分享图片



  如果M = 1,也就是点列只包含一个点的情况。那么有4种序列。明显都符合要求。
  所以一共就有1 + 3 + 6 + 4一共14种序列符合要求。
数据规模和约定
  对于25%的数据,N <= 50;对于40%的数据,N <= 700;对于60%的数据,N <= 2000;对于70%的数据,N <= 4000;对于100%的数据,1 <= N <= 7000。
  对于100%的数据,有1 <= Q <= 1000000000。
  对于50%的数据,保证对任何的i,x[i]和y[i]是1到N之间的整数;对于100%的数据,保证对任何的i,x[i]和y[i]都是1到2000000000之间的整数。
  对于100%的数据,保证有当i != j时,有x[i] != x[j]且y[i] != y[j]。
/*
    首先把点按照x坐标排序(不是y坐标)
    设dp[i][j][0/1]代表只考虑前i个点,以第j个点为起点,下一个点在它的左边/右边的方案数.
    当i增加1时,从右到左 对每个之前的点考虑第i个点造成的贡献. 
    当这个点在第i个点以上时,第i个点可以更新这个点的dp值;
    当这个点在第i个点以下时,这个点可以更新第i个点的dp值.
    显然是可以滚动数组的.
    复杂度O(n*n)
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node{
    int x,y;
    bool operator < (const node o)const{
        return x<o.x;
    }
}pot[7010];
int n,md,dp[7010][2];
int main(){
    scanf("%d%d",&n,&md);
    for(int i=1;i<=n;i++)scanf("%d%d",&pot[i].x,&pot[i].y);
    sort(pot+1,pot+n+1);
    for(int i=1;i<=n;i++){
        dp[i][0]=dp[i][1]=1;
        for(int j=i-1;j>=1;j--){
            if(pot[j].y<pot[i].y){
                dp[i][0]+=dp[j][1];
                if(dp[i][0]>=md)dp[i][0]-=md;
            }
            else{
                dp[j][1]+=dp[i][0];
                if(dp[j][1]>=md)dp[j][1]-=md;
            }
        }
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        ans+=dp[i][0];
        if(ans>=md)ans-=md;
        ans+=dp[i][1];
        if(ans>=md)ans-=md;
    }
    ans-=n;
    if(ans<0)ans+=md;
    printf("%d\n",ans);
    return 0;
}

 

以上是关于清橙 A1210. 光棱坦克的主要内容,如果未能解决你的问题,请参考以下文章

清橙A1339. JZPLCM(顾昱洲)

关于红警的RULES.INI的问题~~~~~~~~~~~~~~~~~~

刷题清橙 A1339 JZPLCM(顾昱洲)

清橙A1212:剪枝

清橙 A1318 加强版:Almost

Java__线程---基础知识全面实战---坦克大战系列为例