hdu5389 Zero Escape(DP)

来源:互联网 发布:怎么减少网络延迟 编辑:程序博客网 时间:2024/05/20 17:59

点击打开链接


题目大意:有n个人,每个人都有个号码,有两个门a和b,现在要使得所有人都通过门(任意一个),进门条件是进入的所有人的数根等于a或者b,求方案数。


解题思路:一个整数的数根公式为:(x-1)%9+1.

用DP做:dp[i][j]表示前i个数选出来数根为j的方案数,状态转移方程也很容易推导,详情看代码,这里不做解释。

这里我们只要考虑n个人的号码组成a有多少种就可以了,因为剩下的都去b了。

但是要考虑到全都去b的情况,故sum==b时加1.

当然也可以考虑n个人号码组成b有多少种,同样的道理。


/* ***********************************************┆  ┏┓   ┏┓ ┆┆┏┛┻━━━┛┻┓ ┆┆┃       ┃ ┆┆┃   ━   ┃ ┆┆┃ ┳┛ ┗┳ ┃ ┆┆┃       ┃ ┆┆┃   ┻   ┃ ┆┆┗━┓ 马 ┏━┛ ┆┆  ┃ 勒 ┃  ┆      ┆  ┃ 戈 ┗━━━┓ ┆┆  ┃ 壁     ┣┓┆┆  ┃ 的草泥马  ┏┛┆┆  ┗┓┓┏━┳┓┏┛ ┆┆   ┃┫┫ ┃┫┫ ┆┆   ┗┻┛ ┗┻┛ ┆************************************************ */#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <stack>#include <set>#include <map>#include <string>#include <math.h>#include <stdlib.h>using namespace std;#define rep(i,a,b) for (int i=(a),_ed=(b);i<=_ed;i++)#define per(i,a,b) for (int i=(b),_ed=(a);i>=_ed;i--)#define pb push_back#define mp make_pairconst int inf_int = 2e9;const long long inf_ll = 2e18;#define inf_add 0x3f3f3f3f#define mod 258280327#define LL long long#define ULL unsigned long long#define MS0(X) memset((X), 0, sizeof((X)))#define SelfType intSelfType Gcd(SelfType p,SelfType q){return q==0?p:Gcd(q,p%q);}SelfType Pow(SelfType p,SelfType q){SelfType ans=1;while(q){if(q&1)ans=ans*p;p=p*p;q>>=1;}return ans;}#define Sd(X) int (X); scanf("%d", &X)#define Sdd(X, Y) int X, Y; scanf("%d%d", &X, &Y)#define Sddd(X, Y, Z) int X, Y, Z; scanf("%d%d%d", &X, &Y, &Z)inline int read(){int ra,fh;char rx;rx=getchar(),ra=0,fh=1;while((rx<'0'||rx>'9')&&rx!='-')rx=getchar();if(rx=='-')fh=-1,rx=getchar();while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra*fh;}//#pragma comment(linker, "/STACK:102400000,102400000")int add(int a,int b){    return (a+b-1)%9 + 1;}int dp[100005][10];int c[100005];int main(){//freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);ios::sync_with_stdio(0);cin.tie(0);int n,a,b,t;t = read();while(t--)    {        n = read(),a = read(),b = read();        int sum = 0;        for(int i=1;i<=n;i++)        {            c[i] = read();            sum = add(sum,c[i]);        }        if(sum != add(a,b))        {            int ans = 0;            if(sum == a)ans++;            if(sum == b)ans++;            printf("%d\n",ans);            continue;        }        MS0(dp);        dp[0][0] = 1;        for(int i=1;i<=n;i++)        {            for(int j=0;j<=9;j++)            {                (dp[i][j] += dp[i-1][j]) %= mod;                (dp[i][add(j,c[i])] += dp[i-1][j]) %= mod;            }        }        if(sum == b)dp[n][a]++;  //都去b门        printf("%d\n",dp[n][a]);        /*        //答案也可以为这个        if(sum == a)dp[n][b]++;        printf("%d\n",dp[n][b]);        */    }return 0;}





顺手贴个官方的做法吧……

转移方程为:dp[i][j] = (dp[i-1][j] + dp[i-1][(j - C[i] + 9) % 9])


#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int MAXN = (int)1e6 + 10;const int MOD = 258280327;int dp[MAXN][10];int A, B, C[MAXN];int n;int main() {    int T;    scanf("%d", &T);    while(T--) {        scanf("%d%d%d", &n, &A, &B);        int sum = 0, ans = 0;        for(int i = 1; i <= n; i++) {            scanf("%d", &C[i]);            sum += C[i];        }        if((A + B) % 9 != sum % 9) {            if(sum % 9 == A % 9) ans++;            if(sum % 9 == B % 9) ans++;            printf("%d\n", ans);            continue;        }        dp[0][0] = 1;        for(int i = 1; i <= n; i++) {            for(int j = 0; j < 9; j++) {                dp[i][j] = (dp[i-1][j] + dp[i-1][(j - C[i] + 9) % 9]) % MOD;            }        }        printf("%d\n", dp[n][A % 9]);    }    return 0;}




0 0
原创粉丝点击