hdu2817A sequence of numbers二分好题

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

//学习了,vc编译器下,64位数是 _int64 , g++下是long long

            //原来问题出在取余和二分上面
            //q的k次方可以二分
            //如果k是偶数的话,q^k == (q^2)的k/2次方
            //如果k是奇数的话,q^k == (q^2)的k/2次方 * q (因为计算机除与2时向下取)
            //只需要在K是奇数的时候保存q就可以当做偶数直接二分了 
            
#include<iostream>
#define FAC 200907
using namespace std;

bool ok;
int t,k;
long long a1,a2,a3,ans,tmp,q,d,q2;
int main (){
    
    cin>>t;
    while(t--)
    {
        cin>>a1>>a2>>a3>>k;
        k--;//为了简便k=k-1 
        if( (a1+a3)==2*a2 )//如果是等差数列 
        {
            d=a2-a1;//ans = (a1+k*d)modFAC
            ans = (a1%FAC + ((k % FAC)*(d % FAC)))%FAC;
            cout<<ans<<endl;
        }
        else{
            q=(a2/a1)%FAC;
            a1%=FAC;
            tmp=1;
            //while(k!=1){
            while(k){
                if(k&1)//如果k是奇数 
                    tmp = (tmp*q)%FAC;
                q=(q*q)%FAC;
                k/=2;
            }
            cout<<(a1*tmp)%FAC<<endl;
            //最后问题变成 q^1 == q^2的1/2次方
            //cout<< (a1*q*tmp)%FAC <<endl;
        }
        //貌似直接取余的话会溢出   (a1*tmp)%FAC == (a1%FAC * tmp%FAC) % FAC  
        //tmp%FAC => (tmp*q) % FAC => 
    }
    return 0;
}

/* 
            //我们要让k-1尽量小,同时意味着q要尽量大
            //如果k-1是个质数,显然不能简化
            //如果从2到sqrt(k-1)的数中找到了因子,则让k-1除于该因子,然后继续循环
            ok=0;            
            while(1){
                q2=1;
                for(int i=2;i*i<k;i++)
                {
                    if(k%i==0)
                    {
                        k/=i;
                        while(i--)//乘i次 
                            q2*=q;
                        q=q2;
                        ok=1;
                        break;
                    }
                }
                if(!ok)//如果k已经是质数了,就不能继续化简 
                    break;
            }
            这么做不行 
*/
原文地址:https://www.cnblogs.com/neverchanje/p/3613466.html