HDU 5230 ZCC loves hacking(DP)

xiaoxiao2021-02-27  148

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

题意; 从1~N-1这些数里选出一些,要求它们的和在区间[L-C,R-C]内,求方案数。 

分析:

1,第一种思路 时间复杂度O(N^2),状态dp【i】【j】表示取1~i 中任意数之和小于j 的方案数。

状态转移:dp【i】【j】=dp【i-1】【j】+dp【i-1】【j-i】;

很明显过不去

2,第二种思路 时间复杂度能过,状态dp【i】【j】表示从1~n-1中取 i 个数之和为j 方案数

状态转移:dp【i】【j】=dp【i】【j-i】+dp【i-1】【j-i】;

dp【i】【j-i】表示这 i 个数可以每个数+1转移到 i个数之和为 j。

dp【i-1】【j-i】表示这 i-1个数每个数+1后 和变成 j-1,之后再填上一个数字1.就有i个数之和为 j。

第一种代码:

#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <stack> #include <map> #include <set> #include <vector> #include <queue> #define mem(p,k) memset(p,k,sizeof(p)); #define rep(a,b,c) for(int a=b;a<c;a++) #define pb push_back //#define lson l,m,rt<<1 //#define rson m+1,r,rt<<1|1 #define inf 0x6fffffff #define ll long long using namespace std; const int maxn=100010; const int mod=998244353; int l,r,c,n; int dp[2][maxn]; int main() { int t; cin>>t; while(t--){ scanf("%d%d%d%d",&n,&c,&l,&r); l-=c,r-=c; r=min(r,(n-1)*n/2); mem(dp,0); int now=1; for(int i=0;i<=r;i++)dp[now][i]=1; for(int i=1;i<n;i++){ now^=1; for(int j=0;j<=r;j++){ if(j>=i) dp[now][j]=(dp[now^1][j-i]+dp[now^1][j])%mod; else dp[now][j]=dp[now^1][j]; //if(j>=l && j<=r)ans=(ans+dp[now][j])%mod; } mem(dp[now^1],0); } cout<<dp[now][r]-(l>=1?dp[now][l-1]:0)<<endl; } return 0; }

第二种代码:

#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <stack> #include <map> #include <set> #include <vector> #include <queue> #define mem(p,k) memset(p,k,sizeof(p)); #define rep(a,b,c) for(int a=b;a<c;a++) #define pb push_back //#define lson l,m,rt<<1 //#define rson m+1,r,rt<<1|1 #define inf 0x6fffffff #define ll long long using namespace std; const int maxn=100010; const int mod=998244353; int l,r,c,n; int dp[2][maxn]; int main() { int t; cin>>t; while(t--){ scanf("%d%d%d%d",&n,&c,&l,&r); l-=c,r-=c; mem(dp,0); dp[0][0]=1; int ans=l==0?1:0,now=1; for(int i=1;i*(i+1)/2<=min(n-1,r);i++){ now^=1; for(int j=i*(i+1)/2;j<=r;j++){ dp[now][j]=(dp[now^1][j-i]+dp[now][j-i])%mod; if(j>=l && j<=r)ans=(ans+dp[now][j])%mod; } mem(dp[now^1],0); } cout<<ans<<endl; } return 0; }
转载请注明原文地址: https://www.6miu.com/read-16614.html

最新回复(0)