[hdu 4959]Poor Akagi 数论(卢卡斯数,二次域运算,等比数列求和)

Poor Akagi

Time Limit: 30000/15000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 131    Accepted Submission(s): 29

Problem Description

Akagi is not only good at basketball but also good at math. Recently, he got a sequence Ln from his teacher. Ln is defined as follow:

$$\Large L(n)=\begin{cases}

2 & \text{ if } n=0 \\

1 & \text{ if } n=1 \\

L(n-1)+L(n-2) & \text{ if } n>1

\end{cases}$$

And Akagi’s teacher cherishes Agaki’s talent in mathematic. So he wants Agaki to spend more time studying math rather than playing basketball. So he decided to ask Agaki to solve a problem about Ln and promised that as soon as he solves this problem, he can
go to play basketball. And this problem is:

Given N and K, you need to find \(\Large\sum\limits_{0}^{N}L_i^K\)

And Agaki needs your help.

Input

This problem contains multiple tests.

In the first line there’s one number T (1 ≤ T ≤ 20) which tells the total number of test cases. For each test case, there an integer N (0 ≤ N ≤ 10^18) and an integer K (1 ≤ K ≤ 100000) in a line.

Output

For each test case, you need to output the answer mod 1000000007 in a line.

Sample Input

3
3 1
2 2
4 3

Sample Output

10
14
443

Source

BestCoder Round #5

题目大意

求卢卡斯数的k次方的前n项和

卢卡斯数为L[0]=2,L[1]=1,L[n]=L[n-2]+L[n-1](n>=2)

题目思路

当时看到题还以为直接依据 zoj 3774 找出二次剩余…… 结果发现1e9+7不存在二次剩余

最后发现了一种非常巧妙的做法

直接依据卢卡斯数的通项公式

则求和公式为

定义二次域

此时直接对二次域进行加、乘操作就可以(最后的结果为整数,故根号五不会存在在结果之中)

重载二次域的加号和乘号,定义二次域的高速幂运算。所有带入公式就可以。

=.=好像这一题的杭电的数据还没有修正

公比为一时直接返回n+1(可能带来溢出)居然AC了

然后正解依旧WA……

这里仅仅放正解代码

/**
**author : ahm001  **
**source : hdu 4959**
**time :  08/21/14 **
**type : math      **
**/
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <ctime>
#include <cctype>
#include <cmath>
#include <string>
#include <cstring>
#include <stack>
#include <queue>
#include <list>
#include <vector>
#include <map>
#include <set>

#define sqr(x) ((x)*(x))
#define LL long long
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define eps 1e-10
#define mod 1000000007

using namespace std;

int cnt=0;

typedef pair <LL,LL> qf;
qf operator + (qf a,qf b)
{
    return make_pair((a.first+b.first)%mod,(a.second+b.second)%mod);
}
qf operator * (qf a,qf b)
{
    // if ((((LL)a.first*(LL)b.first)%mod+((LL)a.second*(LL)b.second)%mod*5ll)%mod<0)
    //     printf("%d %d %d %d\n",a.first,a.second,b.first,b.second);
    if (a.first<0) a.first+=mod;
    if (b.first<0) b.first+=mod;
    if (a.second<0) a.second+=mod;
    if (b.second<0) b.second+=mod;
    return make_pair((((LL)a.first*(LL)b.first)%mod+((LL)a.second*(LL)b.second)%mod*5ll)%mod,
    (((LL)a.first*(LL)b.second)%mod+((LL)a.second*(LL)b.first)%mod)%mod);
}

qf pow(qf a, LL x)
{
    qf res(1,0);
    qf multi=a;
    while (x)
    {
        if (x&1)
        {
            res=res*multi;
        }
        multi=multi*multi;
        x/=2;
    }
    return res;
}
LL pow(LL a,LL b)
{
    LL res=1;
    LL multi=a;
    while (b)
    {
        if (b&1)
        {
            res=res*multi%mod;
        }
        multi=multi*multi%mod;
        b/=2;
    }
    return res;
}
qf acce(qf a,LL b)
{
    qf ans=make_pair(1,0);
    // if (a==ans) return make_pair(b+1,0);//这条语句去掉后AC了。可是n+1不取模将会造成后面的结果爆掉
    qf powe=a;
    qf sum=a;
    qf multi=make_pair(1,0);
    while (b)
    {
        if (b&1)
        {
            ans=ans+(multi*sum);
            multi=multi*powe;
        }
        sum=sum*(powe+make_pair(1,0));
        powe=powe*powe;
        b/=2;
    }
    return ans;
}
LL inv[100005];
qf r1[100005],r2[100005];

void egcd (LL a,LL b,LL &x,LL &y)
{
    if (b==0)
    {
        x=1,y=0;
        return ;
    }
    egcd(b,a%b,x,y);
    LL t=x;
    x=y;y=t-a/b*y;
}
int main()
{
    LL x,y;
    for (LL i=1;i<=100000;i++)
    {
        egcd(i,mod,x,y);
        x=(x+mod)%mod;
        inv[i]=x;
    }

    r1[0]=make_pair(1,0);
    r2[0]=make_pair(1,0);
    for (int i=1;i<=100000;i++)
    {
        r1[i]=r1[i-1]*make_pair(1,1);
        r2[i]=r2[i-1]*make_pair(1,-1);
    }

    int T;
    scanf("%d",&T);

    while (T--)
    {
        cnt=0;
        LL n,m;
        scanf("%I64d%I64d",&n,&m);
        // n=1e18;
        // m=1e5;

        qf ans=make_pair(0,0);
        LL Ca=1;
        LL v=pow(inv[2],m);
        for (LL i=0;i<=m;i++)
        {
            // printf("%lld\n",Ca);
            qf p(Ca,0);
            qf tmp=r1[i]*r2[m-i]*make_pair(v,0);
            tmp=acce(tmp,n);
            tmp=tmp*p;
            ans=ans+tmp;
            Ca=Ca*(m-i)%mod;
            Ca=Ca*inv[i+1]%mod;
        }
        LL aa=(LL)ans.first;
        printf("%I64d\n",aa);
        // printf("%d %d \n",ans.first,ans.second);
        // printf("%d\n",cnt);
    }
    return 0;
}
时间: 2024-10-26 15:57:25

[hdu 4959]Poor Akagi 数论(卢卡斯数,二次域运算,等比数列求和)的相关文章

hdu 4956 Poor Hanamichi 解题报告

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4956(它放在题库后面的格式有一点点问题啦,所以就把它粘下来,方便读者观看) 题目意思:给出一个范围 [l, r] 你, 问是否能从中找到一个数证明 Hanamichi’s solution 的解法是错的. Hanamichi’s solution 是这样的: 对于某个数 X,从右往左数它的每一位数字(假设第一位是从0开始数).它 偶数位的数字之和 -  奇数位的数字之和  = 3  而且 这个 X

HDU 4937 Lucky Number(数论)

HDU 4937 Lucky Number 题目链接 题意:给定一个数字,求它再x进制下,每位进制位上都只有3,4,5,6,求这样的x有多少种,如果无限种输出-1 思路:首先3 4 5 6特判掉是无限的,很容易想到就不证明了,然后就是枚举数字的最后一位3,4,5,6,然后进制数肯定来自这个数字的因子,因为剩下的数字肯定是a1x^1 + a2x^2 + a3x^3...这样的,这样只要在因子中找进制,去判断即可.找因子的方法用先分解再dfs找,直接试除会超时 代码: #include <cstdi

HDU 1695 GCD (数论-整数和素数,组合数学-容斥原理)

GCD Problem Description Given 5 integers: a, b, c, d, k, you're to find x in a...b, y in c...d that GCD(x, y) = k. GCD(x, y) means the greatest common divisor of x and y. Since the number of choices may be very large, you're only required to output t

[BestCoder Round #5] hdu 4956 Poor Hanamichi (数学题)

Poor Hanamichi Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 743    Accepted Submission(s): 275 Problem Description Hanamichi is taking part in a programming contest, and he is assigned to so

hdu 5177 (1e18范围的卡特兰数)

hdu 5177 (1e18范围的卡特兰数) 题意: 求第n个卡特兰数,模3814697265625 (5^18) 限制: 有20组数据,1 <= n <= 1e18 思路: 1. 卡特兰数的表达式: ans = 1/(n+1) * C(2*n,n) -> ans = 1/(n+1) * (2n)! / n! / n!    ---1式 2. 因为要模5^18,求逆元要求互质,所以先把"1式"中的因子5全部去掉 3. 然后看不含因子5的阶乘,f(n!) 4. 设g(x

hdu 1280 前m大的数 哈希

前m大的数 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 10574    Accepted Submission(s): 3686 Problem Description 还记得Gardon给小希布置的那个作业么?(上次比赛的1005)其实小希已经找回了原来的那张数表,现在她想确认一下她的答案是否正确,但是整个的答案是很庞大的表,小

HDU 4861 Couple doubi(数论)

HDU 4861 Couple doubi 题目链接 题意:给定k,p,有k个球,每个球的值为1^i+2^i+...+(p-1)^i (mod p) (1 <= i <= k),现在两人轮流取球,最后球的值总和大的人赢,问先手是否能赢 思路:先手不可能输,非赢即平,那么只要考虑每种球的值, 利用费马小定理或欧拉定理,很容易得到该函数的循环节为p - 1, 那么i如果为p - 1的倍数,即为循环节的位置,那么每个值都为1,总和为p - 1 如果i不在循环节的位置,任取一个原根g,根据原根的性质,

hdu 4956 Poor Hanamichi BestCoder Round #5(数学题)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4956 Poor Hanamichi Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 7    Accepted Submission(s): 4 Problem Description Hanamichi is taking part in

HDU 4956 Poor Hanamichi

HDU 4956 Poor Hanamichi 题目链接 思路:直接从l往上找判断即可 代码: #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; typedef long long ll; int t; ll l, r; bool judge(ll num) { ll flag = 1; ll ans = 0; whi