zoj 2900 dp or 线段树

来源:互联网 发布:联通卡蜂窝数据打不开 编辑:程序博客网 时间:2024/04/28 18:36

好久没刷题了。。。妈的  自从打铁回来之后一个星期用来恢复心情,然后一直赶各种报告,各种考试。。。。

妈的,咳了一个星期都没好。。。。

要死了。。。。

今天来刷下题,一不小心跑了最快。。。。。

dp【i】【j】表示i个数,最后一个数是j的种类数,然后每次只需要跟新num【k】就行。。。

AC代码如下:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;long long dp[2200][120];int N, K, P;int num[2200];long long MOD;inline int lowbit( int x ){    return (x&(-x));}long long getsum( int pos, int x ){    long long sum = 0;    while( x ){        sum += dp[pos][x];        if( sum >= MOD ){            sum -= MOD;        }        x -= lowbit( x );    }    return sum;}void updata( int pos, int x, long long val ){    while( x <= 110 ){        dp[pos][x] += val;        if( dp[pos][x] >= MOD ){            dp[pos][x] -= MOD;        }        x += lowbit( x );    }}int main(){    while( scanf( "%d%d%d%lld", &N, &K, &P, &MOD ) != EOF ){        memset( dp, 0, sizeof( dp ) );        for( int i = 0; i < N; i++ ){            scanf( "%d", &num[i] );            num[i]++;        }        for( int i = 0; i < N; i++ ){            for( int j = i + 1; j >= 1; j-- ){                int l = max( 1, num[i] - P );                int r = min( 110, num[i] + P );                long long temp1 = getsum( j - 1, r );                long long temp2 = getsum( j - 1, l - 1 );                updata( j, num[i],  ( temp1 - temp2 + MOD ) % MOD );            }            updata( 1, num[i], 1 );        }        long long ans = 0;        for( int i = K; i <= N; i++ ){            ans = ( ans + getsum( i, 110 ) ) % MOD;        }        printf( "%lld\n", ans );    }    return 0;}/*2 1 1 101 1*/


0 0
原创粉丝点击