hdu 5230 ZCC loves hacking(整数拆分的变形+前缀和)

ZCC loves hacking

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/131072 K (Java/Others)
Total Submission(s): 393    Accepted Submission(s): 144


Problem Description
Now, a Codefires round is coming to end. ZCC has got C(0C106) points by solving all problems. He is amazed that all other contestants in his room have also solved the hardest problem. So he concludes that most contestants are gonna get FST after the contest except the top rated coder Memset137. Before that, ZCC will hack them to make his score higher. There are N(1N100000) other contestants in ZCC's room. They are sorted by their ratings(So Memset137 is the N-th contestant). When ZCC successfully hacks the i-th contestant, he will get i points. You may assume ZCC can hack every wrong solution in very little time, and Memset137 is the contestant with number N. During that time, other contestants won't bother him.

Since ZCC is a modest winner, he doesn't want his score to be too high. ZCC wonders how many ways are there that he can choose some contestants' solutions except the one submitted by Memset137 and hack them so that his final score is between L and R (CLR<C+N) .

Obviously the result can be very large, so please output it modulo 998244353.
 

Input
The first line contains an integer T(T=100) which denotes the number of test cases.
For each test case, there will be four integers N(N105) , C , L , R in a single line.

For 95% of the test cases, N2000 .
For 97% of the test cases, N50000 .
 

Output
For each test case, print a single integer which is the answer.
 

Sample Input
  
3 3 0 1 2 5 13 14 17 100 0 23 59
 

Sample Output
  
2 6 90567
 

Source
题目分析:
整数拆分,求一下前缀和,区间和很容易就求出来了,水题一个
 
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define MAX 100007
#define MOD 998244353

using namespace std;

int five ( int x )
{
    return x*(3*x-1)/2;
}

int dp[MAX];
int q[MAX];
int sum[MAX];

void init ( )
{
    dp[0] = 1;
    for ( int i = 1 ; i < MAX ; i++ )
    {
        for ( int j = 1 ; ; j++ )
        {
            int k = five(j);
            if ( k > i ) break;
            if ( j&1 ) dp[i] = dp[i] + dp[i-k];
            else dp[i] = dp[i] - dp[i-k];
            dp[i] %= MOD;
            k = five(-1*j);
            if ( k > i ) break;
            if ( j&1 ) dp[i] = dp[i] + dp[i-k];
            else dp[i] = dp[i] - dp[i-k];
            dp[i] %= MOD;
        }
        dp[i] = (dp[i]%MOD+MOD)%MOD;
    }
    /*for ( int i = 1 ; i < 10 ; i++ )
        printf ( "%d " , dp[i] );
    puts("");*/
    q[0] = dp[0];
    for ( int i = 1 ; i < MAX ; i++ )
    {
        q[i] = dp[i];
        for ( int j = 1 ; ; j++ )
        {
            int k = five(j)*2;
            if ( k > i ) break;
            if ( j&1 ) q[i] -= dp[i-k];
            else q[i] += dp[i-k];
            q[i] %= MOD;
            k = five(-1*j)*2;
            if ( k > i ) break;
            if ( j&1 ) q[i] -= dp[i-k];
            else q[i] += dp[i-k];
            q[i] %= MOD;
        }
        q[i] = (q[i]%MOD+MOD)%MOD;
    }
    /*for ( int i = 0 ; i < 10 ; i++ )
        printf ( "%d " , q[i] );
    puts ("");*/
    sum[0] = q[0];
    for ( int i = 1 ; i < MAX ; i++ )
        sum[i] = (sum[i-1] + q[i])%MOD;
}

int t,n,c,l,r;

int main ( )
{
    init();
    scanf ( "%d" , &t );
    while ( t-- )
    {
        scanf ( "%d%d%d%d" , &n , &c , &l , &r );
        l -= c;
        r -= c;
        n--;
        if ( l == 0 ) printf ( "%d\n" , sum[r] );
        else printf ( "%d\n" , ((sum[r] - sum[l-1])%MOD+MOD)%MOD );
    }

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值