BZOJ4833: [Lydsy1704月赛]最小公倍佩尔数

42 篇文章 0 订阅
11 篇文章 0 订阅

可以看一下这篇东西


推一下f(n),e(n)的柿子,有
(1+2)n+1 ( 1 + 2 ) n + 1
=(1+2)n(1+2) = ( 1 + 2 ) n ( 1 + 2 )
=(e(n)+f(n)2)(1+2) = ( e ( n ) + f ( n ) 2 ) ( 1 + 2 )
=e(n)+2f(n)+(f(n)+e(n))2 = e ( n ) + 2 f ( n ) + ( f ( n ) + e ( n ) ) 2
于是 e(n+1)=e(n)+2f(n),f(n+1)=f(n)+e(n) e ( n + 1 ) = e ( n ) + 2 f ( n ) , f ( n + 1 ) = f ( n ) + e ( n )
f(n+1)=2f(n)+f(n1) f ( n + 1 ) = 2 f ( n ) + f ( n − 1 )

然后类比斐波那契的性质: ( fib[a],fib[b] )=fib[(a,b)] (   f i b [ a ] , f i b [ b ]   ) = f i b [ ( a , b ) ]
长得像 f(n+1)=af(n)+bf(n1) f ( n + 1 ) = a f ( n ) + b f ( n − 1 ) 的东西很多都有这个性质?
反正这题有= =


那么做个lcm,gcd的容斥,令全集 S=1,2,3....n S = 1 , 2 , 3.... n
g(n)=lcm(f(i),iS) g ( n ) = l c m ( f ( i ) , i ∈ S )

g(n)=TS,Tϕf(gcd(T))(1)|T|1 g ( n ) = ∏ T ⊆ S , T ≠ ϕ f ( g c d ( T ) ) ( − 1 ) | T | − 1


我们定义一个 h(n) h ( n ) ,满足 f(i)=d|ih(d) f ( i ) = ∏ d | i h ( d ) ,那么 h(i)=d|if(d)μ(i/d) h ( i ) = ∏ d | i f ( d ) μ ( i / d )

那么

g(n)=TS,Tϕ( d|gcd(T) h(d))(1)|T|1 g ( n ) = ∏ T ⊆ S , T ≠ ϕ (   ∏ d | g c d ( T )   h ( d ) ) ( − 1 ) | T | − 1

g(n)=dh(d)TS,Tϕ,d|gcd(T)(1)|T|1 g ( n ) = ∏ d h ( d ) ∑ T ⊆ S , T ≠ ϕ , d | g c d ( T ) ( − 1 ) | T | − 1

然后观察 h(d) h ( d ) 的指数 TS,Tϕ,d|gcd(T)(1)|T|1 ∑ T ⊆ S , T ≠ ϕ , d | g c d ( T ) ( − 1 ) | T | − 1 这个东西
因为 Tϕ T ≠ ϕ ,于是当 dS d ∈ S 时值为1,否则为0

于是有 g(n)=ni=1h(i) g ( n ) = ∏ i = 1 n h ( i )

code:

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;

const int maxn = 1e6+10;

int p[maxn],pri,mu[maxn];
bool v[maxn];
void pre()
{
    mu[1]=1;
    for(int i=2;i<maxn;i++)
    {
        if(!v[i]) p[++pri]=i,mu[i]=-1;
        for(int j=1,k=p[j]*i;k<maxn;j++,k=p[j]*i)
        {
            v[k]=true;
            if(i%p[j]==0) break;
            mu[k]=-mu[i];
        }
    }
}

int mod,n;
int pw(int x,int k)
{
    int re=1;
    for(;k;k>>=1,x=(ll)x*x%mod) if(k&1)
        re=(ll)re*x%mod;
    return re;
}
int inv(int x){ return pw(x,mod-2); }
int f[maxn],invf[maxn],g[maxn];

int main()
{
    //freopen("tmp.in","r",stdin);
    //freopen("tmp.out","w",stdout);

    // fi=2fi-1+fi-2
    pre();

    int T; scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&mod);
        f[0]=0,f[1]=1; for(int i=2;i<=n;i++) f[i]=(2ll*f[i-1]+f[i-2])%mod;
        for(int i=1;i<=n;i++) invf[i]=inv(f[i]);

        for(int i=1;i<=n;i++) g[i]=1;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;i*j<=n;j++) if(mu[j])
                g[i*j]=(ll)g[i*j]*(mu[j]==1?f[i]:invf[i])%mod;
        }
        int ans=0;
        for(int i=1,t=1;i<=n;i++)
        {
            t=(ll)t*g[i]%mod;
            ans=(ans+(ll)t*i%mod)%mod;
        }
        ans=(ans+mod)%mod;
        printf("%d\n",ans);
    }


    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值