HDU2817

HDU2817 A sequence of numbers

现在有一个由整数组成的序列,可能是等差数列,也可能是等比数列,但是只给出前3个数,要求你求数列中第k个数% 200907的结果。所给数列是一个非递减数列。

输入:首先是一个t表示输入的实例个数,以下t行每行代表一个实例。每行包括4个整数,前3个整数在[0, 2^63)范围内,表示数列的头3个数,第4个数是k表示要求的数列中的第k个数。其中0 < k <= 10^9。

输出:输出数列中第k个数%200907的结果。

分析:特殊情况,一个非递减数列如果既是等差又是等比数列,那么它一定是有一系列相同的数组成的。或者说如果数列的前2个数相等,那么整个数列都相等。

假设读入的前3个数分别为a1,a2,a3.

如果a2-a1 == a3-a2 那么数列等差,公差为d=a2-a1.所求的第k个数为 ak = a1+d*(k-1)

所求为ak%mod

否则数列为等比数列,公比为p=a2/a1且公比必定为整数(可证),所求的第k个数为ak = a1*(p^(k-1))。所求为ak%mod。该结果要用pow_mod的幂运算分治法求。

求等比的时候 如果 int p=a2/a1;则必定出错,因为p可能超出int范围。

对于这种数据正好几乎要超过int的范围却远小于long long的范围的题目,直接全部用long long

AC代码:

//对于这种数据正好几乎要超过int的范围却远小于long long的范围的题目,直接全部用long long
#include<cstdio>
using namespace std;
const long long mod = 200907;

long long pow_mod(long long x,long long a,long long n)//a^b mod mod
{
    if(a==0) return 1;
    long long ans = pow_mod(x,a/2,n);
    long long temp = (ans*ans)%n;
    if(a%2) temp = (temp*x)%n;
    return temp;
}

/*
long long pow_mod(long long a,long long b,long long n)  //a^b mod n
{
    long long ret=1;
    for (; b; b>>=1,a=(long long)(((long long)a)*a%n))
        if (b&1)
            ret=(long long)(((long long)ret)*a%n);
    //printf("%d\n",ret);
    return ret;
}
*/
int main()
{
    int t;
    scanf("%d",&t);

    while(t--)
    {
        long long  a1,a2,a3;
        long long k;
        scanf("%I64d%I64d%I64d%I64d",&a1,&a2,&a3,&k);
        //if(a1==a2)
        // printf("%.0lf\n",a1%mod);

        if(a2-a1==a3-a2)//等差数列
        {
            /*
            long long d = (long long)(a2-a1);
            long long a = (long long)a1;
            int temp = (a%mod+((d%mod)*((k-1)%mod)))%mod;
            printf("%d\n",temp);
            */
            long long d = (a2-a1)%mod;
            long long temp = ((a1%mod)+((d%mod)*((k-1)%mod)))%mod;
            printf("%I64d\n",temp);

        }
        else//等比数列
        {
            /*
            long long p1 = (a2/a1);
            long long p = (long long)p1;
            long long a = (long long)a1;
            int temp = ((a%mod)*(pow_mod(p,k-1,mod)))%mod;
            printf("%d\n",temp);
            */
            long long p=a2/a1;//p的值可能超过int的范围,如果此处用int则必定WA
            long long  temp = ((a1%mod)*(pow_mod(p,k-1,mod)))%mod;
            printf("%I64d\n",temp);

        }

    }
    return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值