HDU 4038 Stone (模拟 快速幂)

来源:互联网 发布:程序员的呐喊下载 编辑:程序博客网 时间:2024/05/16 14:44

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4038

这个题目wa的数次,数据非常严格,还有所有数据类型都要为long long的比较好

这个题目首先要知道基本的数学知识

首先判断负数的个数,如果为偶数,那么负数不用管了,最后乘起来就OK了

如果负数个数是奇数,那么就把尽可能的在m满足的情况下让这个负数向0靠近

完成之后把所有的0在m的允许的情况下把0变成1,因为0不变成1结果都是0,

之后把所有1变成2,因为1对结果不起作用,但是变成2就立即变成2倍,之后

把2变成3,因为3*3=9 > 2*2*2=8,之后完成

最后看m有没有剩余,之后的解释看程序中的若干if else

#include <iostream>#include <string.h>#include <stdio.h>#include <algorithm>#include <cmath>using namespace std;#define maxn 110000#define MOD 1000000007#define my_abs(a) (a>0?a:-a)#define LL __int64LL rec[maxn];LL m,n;LL MUL(LL a,LL k,LL mo){   LL b=1;   while(k>=1){    if(k%2==1) b=(a*b)%mo;    a=(a*a)%mo,k=k/2;  }  return b;}int solve(){    LL i,j,k;    bool flag=false;    LL a,b,ans=1,pos;    for(i=1;i<n;i++) if(rec[i] >= 0) break;    k=i-1;    if(rec[k] < 0){//表示确实有小于0的,如果为奇数个把最大的那个负数变成0(在m允许的条件下,如果不行尽量向0靠近)        if(k%2==0){            if(my_abs(rec[k]) <=m) m-=my_abs(rec[k]),rec[k]=0;            else rec[k]+=m,m=0;        }        else        k++;    }    for(i=0;i<n && m>0;i++){//把所有为0的变成1        if(rec[i]==0 ) rec[i]=1,m--,pos=i;    }    for(i=k;i<n&& m>0;i++){//把所有为1的变成2        if(rec[i]==1 ) rec[i]=2,m--,pos=i;    }    for(i=0;i<n && m>0;i++){//把所有为2的变成3        if(rec[i]==2) rec[i]=3,m--,flag=true,pos=i;    }   if (m >= 3){   ans = ans * MUL(3, (m/3)-1,MOD) % MOD;   if (m % 3 == 0)    ans = ans*3 % MOD;   else if (m % 3 == 1)    ans = ans*4 % MOD;   else ans = ans*2*3 % MOD;  }else   if(m == 2) ans = ans * 2 %MOD;   else   if(m == 1) rec[pos]++;   for(i = 0; i < n; i++)   ans = ans*rec[i]%MOD;   printf("%I64d\n",ans%MOD);   return 0;}int main(){    LL i,j,k=0,t;    scanf("%I64d",&t);    while(t--){        scanf("%I64d%I64d",&n,&m);        for(i=0;i<n;i++)        scanf("%I64d",&rec[i]);        sort(rec,rec+n);        printf("Case %I64d: ",++k);        solve();    }    return 0;}