• 国家—(分治)


    【题目描述】

    给定正整数 n , p 和非负整数 a , b ,求 an+an-1b+an-2b2+…+a2bn-2+abn-1+bn,例如当n=1时,该结果等于 a+b 。由于答案可能很大,请对 p 取模。

    【输入格式】

    ▲多组数据

    第一行,一个正整数T,表示数据组数。

    接下来 T 行,每行四个整数 n , a , b , p ,表示一组数据,相邻两个数之间有空格隔开。

    【输出格式】

    共 T 行,每行一个非负整数,表示一组数据的答案。

    【样例输入】

    3

    2 3 3 233

    5 1 2 100

    1000 233 666 998244353

    【样例输出】

    27

    63

    952904376

    【数据规模及约定

    对于30%的数据,满足 T≤10,n,a,b≤106p=109+7。

    对于60%的数据,满足 T≤10,000,n,a,b≤109p=109+7。

    另有10%的数据,满足 a=0。

    另有10%的数据,满足 a=1。

    对于100%的数据,满足 T≤30,000,n,a,b,p≤1012

    思路:

      可以采取分治来求解。

      先从简单入手: 如:

      当 n=5 时,有: a5+a4b+a3b2+a2b3+ab4+b→ 可以将序列从中间分为 a5+a4b+a3b2  和 a2b3+ab4+b5

      那么从中提出 a3 和 b3 可得:a3( a2+ab+b) + b3( a2+ab+b) →又可以合并为 ( a3+b) × ( a2+ab+b)。

      后面的式子还可以继续分治: 可以看作是 n=2 时所要求的式子。

      但这时,n 为偶数,式子是一个三项式,无法从中间直接分解。则考虑添项:a2+ab+b= a2+ab+ab+b2-ab 。

      最终为:(a+b)(a+b)-ab 。

      所以 a5+a4b+a3b2+a2b3+ab4+b= ( a3+b) × ( (a+b)(a+b)-ab )。

    从上述简单的求解可以看出:

      当 n 为奇数时,可以将式子直接二分递归下去(dfs(n>>1)),当 n 为奇数时,将式子添项后再二分递归(dfs((n>>1)+1)-ksm((a*b),(n>>1))) 奇数 n 的 -ksm((a*b),(n>>1)) 是减去中间添加的项。

    代码实现:  

    long long dfs(long long k)//k,此时的二分 n 的值
    {
      if(k==1) return (a+b)%p;
      if(k&1) return ksc( ( ksm(a,(k>>1)+1,p)+ksm(b,(k>>1)+1,p) )%p , dfs(k>>1) ,p)%p;// n 为奇数
      return ( ksc( ( ksm(a,k>>1,p)+ksm(b,k>>1,p) )%p , dfs(k>>1) ,p)%p + ( p - ksm(ksc(a,b,p),k>>1,p) ) )%p;
    }//ksc 为O(1)快速乘,ksm 为快速幂,p 为模数

    完整代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<cstdlib>
    #include<stack>
    #include<vector>
    #include<queue>
    #include<deque>
    #include<map>
    #include<set>
    using namespace std;
    long long T;
    long long n,a,b,p;
    inline long long read()
    {
        long long kr=1,xs=0;
        char ls;
        ls=getchar();
        while(!isdigit(ls))
        {
            if(!(ls^45))
                kr=-1;
            ls=getchar();
        }
        while(isdigit(ls))
        {
            xs=(xs<<1)+(xs<<3)+(ls^48);
            ls=getchar();
        }
        return xs*kr;
    }
    inline long long ksc(long long x,long long y,long long mod)
    {
        long long tmp=(x*y-(long long)((long double)x/mod*y+1.0e-8)*mod);
        return tmp<0 ? tmp+mod : tmp;
    }//O(1)快速乘 
    inline long long ksm(long long x,long long y,long long mod)
    {
        if(y==0) return 1;
        if(y==1) return x;
        if(y&1)
        {
            long long res=ksm(x,y>>1,mod);
            res=ksc(res,res,mod);
            res=ksc(res,x,mod);
            return res%mod;
        }
        else
        {
            long long res=ksm(x,y>>1,mod);
            return res=(ksc(res,res,mod));
        }
    }//快速幂 
    long long dfs(long long k)
    {
        if(k==1) return (a+b)%p; 
        if(k&1) return ksc(  ( ksm(a,(k>>1)+1,p)+ksm(b,(k>>1)+1,p) )%p , dfs(k>>1)  ,p)%p;
        return (  ksc( ( ksm(a,k>>1,p)+ksm(b,k>>1,p) )%p , dfs(k>>1) ,p)%p + ( p - ksm(ksc(a,b,p),k>>1,p) )  )%p;
    }//分治(关键) 
    int main()
    {
        freopen("guojia.in","r",stdin);
        freopen("guojia.out","w",stdout);
        T=read();
        while(T--)
        {
            n=read(),a=read(),b=read(),p=read();
            if(a==0)//特判 a 为 0 的情况 
            {
                printf("%lld
    ",ksm(b,n,p));
                continue;
            }
            printf("%lld
    ",dfs(n));//把 n 丢进递归函数二分求出答案 
        }
    return 0;
    }
  • 相关阅读:
    ASP.NET Web API 框架研究 Self Host模式下的消息处理管道
    ASP.NET Web API 框架研究 Web Host模式下的消息处理管道
    ASP.NET Web API 框架研究 核心的消息处理管道
    ASP.NET Web API 框架研究 Web Host模式路由及将请求转出到消息处理管道
    ASP.NET Web API 框架研究 ASP.NET Web API 路由
    ASP.NET Web API 框架研究 ASP.NET 路由
    ASP.NET Web API 入门 (API接口、寄宿方式、HttpClient调用)
    MVVM模式
    RESTful Web API 理解
    C# 函数式编程及Monads.net库
  • 原文地址:https://www.cnblogs.com/lck-lck/p/9739583.html
Copyright © 2020-2023  润新知