代码改变世界

srm565 div1

2013-01-12 17:11  macaroniz  阅读(146)  评论(0)    收藏  举报

250pt

很简单的dp,没有什么好说的。

#define N 51
#define MAXPRICE 102
class MonstersValley
{
public:
    long long dp[N][MAXPRICE];
    long long maxx(long long a,long long b)
    {
        if(a < b) return b;
        return a;
    }
    int minimumPrice(vector<long long> dread, vector <int> price)
    {
        int n = dread.size();
        memset(dp,0xff,sizeof dp);
        dp[0][0] = 0;
        for(int i = 1;i <= n;i++)
        {
            for(int p = 0;p <= n*2+1;p++)
            {
                if(dp[i-1][p] != -1 && dp[i-1][p] >= dread[i-1]) dp[i][p] = dp[i-1][p];
                int v = p - price[i-1];
                if(v >= 0 && dp[i-1][v] != -1)
                    dp[i][p] = maxx(dp[i][p],dp[i-1][v] + dread[i-1]);
                //printf("v:%d dp[i-1][v]:%I64d i:%d p:%d dp:%I64d\n",v,dp[i-1][v],i,p,dp[i][p]);
            }
        }
        for(int p = 0;p <= n*2+1;p++)
            if(dp[n][p] >= dread[n-1])
                return p;
    }
};

 

500pt

看出来这题其实就是个nim游戏的变种,并且对于每个数字,石子数(操作数)实际上就是他的质因数个数(若X = p1^n1 * p2 ^ n2.... ,p1,p2,..pn都是质数,质因数个数就是n1+n2+...)即可。

有个难点在于如何快速的求出sigma nim(x),详细的部分可以看程序。

int nim[1000000];
int val[1000000];
class TheDivisionGame
{
public:

    vector<int> prime;

    int facNum(int L,int R)
    {
        memset(nim,0,sizeof nim);
        for(int i = L;i <= R;i++)
            val[i-L] = i;
        for(int i = 2;i <= 100000;i++)
            for(int j = L/i*i;j <= R;j+=i)
                if(j >= L)
                {
                    while(val[j - L] % i == 0)
                    {
                        nim[j - L]++;
                        val[j - L] /= i;
                    }
                }
        for(int i = L;i <= R;i++)
            if(val[i - L] != 1) nim[i - L]++;
        return 0;
    }

    long long countWinningIntervals(int L, int R)
    {
        long long ans = 0;
        map<int,int> hash;
        facNum(L,R);
        int sumNim = 0;
        for(int i = L;i <= R;i++)
        {
            sumNim ^= nim[i-L];
            ans += hash[sumNim];
            if(sumNim == 0) ans++;
            hash[sumNim]++;
        }
        return 1ll*(1 + R-L + 1) * (R - L + 1) / 2 - ans;
    }

};