• 牛客练习赛41 B. 666RPG


      题目大意就是给n个数,然后有n个回合,在第i个回合操作有2种,一种是对当前数*-1,第二种是对当前数+ai,问你n回合后数变成-666的操作方案数是多少?另外数的初始值是0,还有在一个合法的方案里,不能有某个回合结束后数变成了666

      这题用的是计数dp,定义dp[i][j]表示第i个回合结束之后,数变成j的方案个数。初始化是dp[0][0]=1,其余为0。状态转移的话是dp[i][-j]+=dp[i-1][j],dp[i][j+a[i]]+=dp[i-1][j],然后跳过666的转移。然后因为数的变化范围是-666*300到666*300当时数组的下标是不能为负数的,所以在这里做了个映射,把-666*300到666*300这个区间映射到-666*300+700*300到666*300+700*300这个区间了,相当于第i个回合结束后数为j的方案数为dp[i][j+700*300],开二维爆内存了,然后就滚掉一维。

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define tmp 210000
    const ll mod=1e8+7;
    ll dp[2][420000];
    int a[305];
    int main()
    {
        int n,pos=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&(a[i]));
        dp[0][0+tmp]=1LL;
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<=(420000-1);j++) dp[(pos+1)%2][j]=0LL;
            for(int j=-199800;j<=199800;j++)
                if(dp[pos][j+tmp])
                {
                    if(j+a[i]!=666)
                        dp[(pos+1)%2][j+a[i]+tmp]=(dp[(pos+1)%2][j+a[i]+tmp]+dp[pos][j+tmp])%mod;
                    if((-1*j)!=666)
                        dp[(pos+1)%2][-1*j+tmp]=(dp[(pos+1)%2][-1*j+tmp]+dp[pos][j+tmp])%mod;
                }
            pos=(pos+1)%2;
            if(i==n)
            {
                cout<<dp[pos][-666+tmp]<<endl;
                return 0;
            }
        }
    }
    
  • 相关阅读:
    nohup: failed to run command `java': No such file or directory
    HDU4845(SummerTrainingDay02-C 状态压缩bfs)
    Codeforces731C(SummerTrainingDay06-M 并查集)
    Codeforces485D(SummerTrainingDay01-K)
    POJ2227(优先队列)
    Codeforces833A
    HDU3534(SummerTrainingDay13-C tree dp)
    Codeforces687C(SummerTrainingDay03-D DP)
    POJ1811(SummerTrainingDay04-G miller-rabin判断素性 && pollard-rho分解质因数)
    HDU6113
  • 原文地址:https://www.cnblogs.com/eason9906/p/11754805.html
Copyright © 2020-2023  润新知