【校内互测】[T1]数学作业(线性筛约数个数)

35 篇文章 0 订阅
20 篇文章 0 订阅

数学作业

题目描述Description
又是一节晚自习,jn 像往常一样流连于梦乡,但突然被同桌的你戳醒时,却发现数学老师正笑呵呵的站在他面前,“拿出你的数学作业,我要检查”,jn 自然不可能在梦中写作业了,然后喜(sang)闻(xin)乐(bing)见(kuang)的事情发生了,数学老师呵呵一笑,“你不用做今晚数学作业了,不是搞 oi 么,给我算这个吧:Fibonacci 数列是这样一个数列:F1 = 1, F2 = 1, F3 = 2 …Fi = Fi-1 + Fi-2 (当 i >= 3)
对于某一个 Fibonacci 数 Fi,有多少个 Fj 能够整除 Fi (j 可以大于等于 i)共有 m 组询问,输出每个问题答案的和 ans,为了方便输入, ni=(ni1a+b)modc+1
jn 自然不会做了,所以找到你来帮助他
输入Input
从 math.in 输入第一行有五个正整数 m,n1,a,b,c
输出Output
输出到 math.out
样例输入SampleInput
2 2 2 1 8
样例输出SampleOutput
6
数据范围Hint
对于 30%的数据,t≤10,n,a,b,c≤1000
对于 100%的数据,t≤3000000 n,a,b,c≤1000000

通过打表,发现 f[j]f[i] 的个数与j|i的个数是相同的,所以只要用线性筛筛出每个数的约数个数就可以了
斐波纳契数列的几条性质:
1.f(0)+f(1)+f(2)++f(n)=f(n+2)1
2.f(1)+f(3)+f(5)++f(2n1)=f(2n)
3.f(2)+f(4)+f(6)++f(2n)=f(2n+1)1
4.[f(0)]2+[f(1)]2++[f(n)]2=f(n)f(n+1)
5.f(0)f(1)+f(2)+(1)nf(n)=(1)n[f(n+1)f(n)]+1
6.f(m+n)=f(m1)f(n1)+f(m)f(n)Ologn
7.[f(n)]2=(1)(n1)+f(n1)f(n+1)
8.f(2n1)=[f(n)]2[f(n2)]2
9.3f(n)=f(n+2)+f(n2)
10.f(2n2m2)[f(2n)+f(2n+2)]=f(2m+2)+f(4n2m)[nm1,n1]

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int d[1000010],t[1000010],prime[1000010];
long long  m,n,a,b,c,maxn,ans,ask[3000010];
bool p[1000010];
inline void shai()
{ 
    int i,j,k=0;
    d[1]=1; t[1]=0;
    for(i=2;i<=maxn;++i)
     {
        if(!p[i]) { prime[++k]=i;  t[i]=1; d[i]=2; }
        for(j=1;j<=k;++j)
         {
            if(i*prime[j]>maxn) break;
            p[i*prime[j]]=true;
            if(i%prime[j]==0)
             {
                d[i*prime[j]]=d[i]/(t[i]+1)*(t[i]+2);
                t[i*prime[j]]=t[i]+1;
                break;
            }
            else d[i*prime[j]]=d[i]*2,t[i*prime[j]]=1;
        }
    }
  return;
}//线性筛约数个数 
int main()
{
    freopen("math.in","r",stdin);
    freopen("math.out","w",stdout);
    int i,j;
    scanf("%I64d%I64d%I64d%I64d%I64d",&m,&n,&a,&b,&c);
    maxn=ask[1]=n;
    for(i=2;i<=m;++i) ask[i]=(ask[i-1]*a+b)%c+1,maxn=max(maxn,ask[i]);
    shai();
    for(i=1;i<=m;++i)
     {
        if(ask[i]%2==1) ans++;
        ans+=d[ask[i]];
    }
    printf("%I64d\n",ans);
    fclose(stdin); fclose(stdout);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值