码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 2813 奇妙的Fibonacci

时间:2015-02-27 18:27:33      阅读:193      评论:0      收藏:0      [点我收藏+]

标签:数论   线性筛   

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2813

题意:
定义Fibonacci数列为F1=1,F2=1,Fi=Fi?1+Fi?2(i>=3)
对于某一个数Fi,求有多少个Fj能够整除Fi (i可以等于j),以及所有满足条件的j的平方之和。询问次数3?106i107

题解:
由定义不难得到

gcd(fibi,fibi+1)=gcd(fibi?1,fibi)=...=gcd(fib1,fib2)=1
以及
fibn+m=fibn?1?fibm+fibn?fibm+1

所以
gcd(fibn+m,fibn)=gcd(fibn?1?fibm,fibn)=gcd(fibn?1,fibn)?gcd(fibm,fibn)=gcd(fibm,fibn)

所以可以归纳得出
gcd(fibi,fibj)=fibgcd(i,j)

那么fibj|fibi等价于j|i

对于每个询问直接算因子明显会超时,考虑用线性筛法来做,埃式筛法复杂度为O(nloglogn),欧式筛法复杂度为O(n),这里使用的是欧拉筛法。
e[i]i的最小质因数次数,d[i]i除去最小质因数的数,g[i]i的因数个数,f[i]i的因数平方和。
对于欧式筛中:

  • imodprime[j]>0i?prime[j]第一次遇见最小质因数,因数个数乘2,f[i?prime[j]]f[i]?prime[j]2+f[i](每个因子乘或不乘prime[j])。
  • imodprime[j]=0prime[j]i?prime[j]的最小质因数但已经遇见过,最小质因数加1,因数个数关于最小质因数部分重算,d[i?prime[j]]不变,f[i?prime[j]]f[i]?prime[j]2+f[d[i?prime[j]]]
  • 注意fib1=fib2=1,这种情况并未算入某些奇数的答案中。

代码:

#include <cstdio>
typedef long long LL;
const int maxc = 664580, maxv = 10000001, mod = 1000000007;
int cnt, prime[maxc], e[maxv], d[maxv], g[maxv], f[maxv], sumg, sumf;
bool vis[maxv];
int main()
{
    int Q, q, A, B, C;
    scanf("%d%d%d%d%d", &Q, &q, &A, &B, &C);
    A %= C, B %= C;
    g[1] = f[1] = 1;
    for(int i = 2; i <= C; ++i)
    {
        if(!vis[i])
        {
            prime[cnt++] = i;
            e[i] = d[i] = 1;
            g[i] = 2;
            f[i] = ((LL)i * i + 1) % mod;
        }
        for(int j = 0, k; j < cnt && (k = i * prime[j]) <= C; ++j)
        {
            vis[k] = 1;
            if(i % prime[j] == 0)
            {
                e[k] = e[i] + 1;
                g[k] = (g[i] / (e[i] + 1)) * (e[k] + 1);
                d[k] = d[i];
                f[k] = (f[i] * ((LL)prime[j] * prime[j] % mod) + f[d[i]]) % mod;
                break;
            }
            else
            {
                e[k] = 1;
                d[k] = i;
                g[k] = g[i] << 1;
                f[k] = f[i] * (((LL)prime[j] * prime[j] + 1) % mod) % mod;
            }
        }
    }
    while(Q--)
    {
        sumg += g[q] + (q & 1);
        sumf += f[q] + 4 * (q & 1);
        if(sumg >= mod) sumg -= mod;
        if(sumf >= mod) sumf -= mod;
        q = (q * (LL)A + B) % C + 1;
    }
    printf("%d\n%d\n", sumg, sumf);
    return 0;
}

BZOJ 2813 奇妙的Fibonacci

标签:数论   线性筛   

原文地址:http://blog.csdn.net/skywalkert/article/details/43970131

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!