UVALive 7505 Hungry Game of Ants (2015Ecfinal)

链接:http://vjudge.net/contest/143339#problem/F

题意:有n个蚂蚁依次排列在长为n-1的绳子上,且蚂蚁大小与其位置相同(位置1的蚂蚁为1,位置n的蚂蚁为n),每个蚂蚁能选择一直向左走或向右走(走到头时反向),蚂蚁速度相同,当蚂蚁相遇时,体积大的吃掉体积小的并继续移动(瞬间吃掉),问使第k个蚂蚁为最后获胜的可能有多少种(总共2^n种可能).


思路:绳子:1,2,3...k...(n-2),(n-1),n

考虑1--k这段:可以找到一个i使1+2+...+i < (i+1)+...+k,则当i右边的蚂蚁都向k方向走时,无论1--i的蚂蚁怎么走,都可以使k为最后获胜.

考虑k--n这段:从k+1遍历到n,使temp=k,每次考虑一个i使1+2+...temp > (temp+1)+...+i(i此时向左走),则在i向右走时,temp应相应向右移动,每次可求出长度为i时,k蚂蚁获胜的可能总数,最后输出dp[n].

#include<stdio.h>  
#include<string.h>  
#include<iostream>  
#include<algorithm>  
using namespace std;  
const long long MAXN = 1000009;  
const long long MOD = 1e9+7;  
long long dpben[MAXN];  
long long erc[MAXN];  
long long dp[MAXN];  
  
long long SUM(long long x)  
{  
    return x*(1+x)/2;  
}  
  
void init()  
{  
    long long ding = 0;  
    erc[0] = 1;  
    erc[1] = 2;  
    for(long long i = 2;i < MAXN;i++){  
        erc[i] = ((erc[i-1]*2)%MOD+MOD)%MOD;  
    }  
    //printf("erc------%lld\n",erc[706]);  
    dpben[0] = 0;  
    dpben[1] = 1;  
    dpben[2] = 2;  
    for(long long i = 3;i < MAXN;i++){  
        while(SUM(ding) < SUM(i)-SUM(ding)){  
            if(ding >= i){  
                break;  
            }  
            ding++;  
        }  
        dpben[i] = ding%MOD;  
    }  
    return ;  
}  
  
  
  
int main()  
{  
    long long t;  
    init();  
      
    scanf("%lld",&t);  
    for(long long Case = 1;Case <= t;Case++){  
        long long have,win;  
        for(long long i = 0;i < MAXN;i++){  
            dp[i] = 0;  
        }  
        scanf("%lld%lld",&have,&win);  
        if(have == 1 && win == 1){  
            printf("Case #%lld: 2\n",Case);  
            continue;  
        }  
          
        dp[win] = (erc[dpben[win]-1])%MOD;  
        long long ding = win;  
        long long temp = dp[win];  
         
        for(long long i = win+1;i <= have;++i){  
            while(ding < i && SUM(ding) < SUM(i)-SUM(ding)){  
                temp = ((temp-dp[ding++])%MOD+MOD)%MOD;  //因为是取摸了的,因此减出来可能为负,要做处理
                //虽然每种蚂蚁都有两种走法,但是当蚂蚁向右走时可能导致值(体积和)过大使目标蚂蚁最终吃不了,因此减去吃不了的情况
            }  
            dp[i] = temp;  
            temp = (temp*2)%MOD; //每个蚂蚁都有两种走法,可能数乘二
        }  
        long long sum = (dp[have]*2)%MOD;  
         
        printf("Case #%lld: %lld\n",Case,sum%MOD);  
    }  
    return 0;  
}  


其中求2次方时可以用矩阵快速幂优化一下,查找可以考虑二分查找,但是ding一定在下次有个变大或变小的趋势,所以也是线性的.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值