Captain obvious and the Rabbit-Man 谜之数学题

题面

这是一个中文版的简化题面,原文请–> 戳这里 <–

题目描述

输入文件

输出文件

数据范围

思路

注:下文中的 Fibi F i b i 表示原文中的F(i),即从 Fib1=1 F i b 1 = 1 Fib2=2 F i b 2 = 2 开始的斐波那契数列。

发现 {ak} { a k } 是未知的,高斯消元 O(n3) O ( n 3 ) 求出所有a可以得到55分。

考虑满分做法,时间复杂度大概为 O(n2) O ( n 2 )

根据二项式定理的经验,感性理解一下可以得出, p(k+1) p ( k + 1 ) 可以表示为 p(1)..p(k) p ( 1 ) . . p ( k ) 的线性组合。

其中 p(t)=ki=1aiFibti p ( t ) = ∑ i = 1 k a i ⋅ F i b i t

不妨设 p(k+1)=t1p(1)+t2p(2)+..+tkp(k) p ( k + 1 ) = t 1 ⋅ p ( 1 ) + t 2 ⋅ p ( 2 ) + . . + t k ⋅ p ( k )

这样我们就有:

ki=1aiFibk+1i=ki=1tikj=1ajFibij ∑ i = 1 k a i ⋅ F i b i k + 1 = ∑ i = 1 k t i ⋅ ∑ j = 1 k a j ⋅ F i b j i

=ki=1kj=1tiajFibij=kj=1ki=1tiajFibij=kj=1ajki=1tiFibij = ∑ i = 1 k ∑ j = 1 k t i ⋅ a j ⋅ F i b j i = ∑ j = 1 k ∑ i = 1 k t i ⋅ a j ⋅ F i b j i = ∑ j = 1 k a j ∑ i = 1 k t i ⋅ F i b j i

交换一下右边的循环变量i和j。

=ki=1aikj=1tjFibji = ∑ i = 1 k a i ∑ j = 1 k t j ⋅ F i b i j

总的写一下:

ki=1aiFibk+1i=ki=1aikj=1tjFibji ∑ i = 1 k a i ⋅ F i b i k + 1 = ∑ i = 1 k a i ∑ j = 1 k t j ⋅ F i b i j

i:aiFibk+1i=aikj=1tjFibji ∀ i : a i ⋅ F i b i k + 1 = a i ∑ j = 1 k t j ⋅ F i b i j 为上式的充分条件。

i:aiFibk+1i=aikj=1tjFibjii:Fibk+1i=kj=1tjFibji ∀ i : a i ⋅ F i b i k + 1 = a i ∑ j = 1 k t j ⋅ F i b i j ⇔ ∀ i : F i b i k + 1 = ∑ j = 1 k t j ⋅ F i b i j

这样 {tk} { t k } 就变得和 {ak} { a k } 无关了。

如果我们能构造一个 {tk} { t k } 使得 i:Fibk+1i=kj=1tjFibji ∀ i : F i b i k + 1 = ∑ j = 1 k t j ⋅ F i b i j ,那么它显然也能使得 p(k+1)=t1p(1)+t2p(2)+..+tkp(k) p ( k + 1 ) = t 1 ⋅ p ( 1 ) + t 2 ⋅ p ( 2 ) + . . + t k ⋅ p ( k )

i:Fibk+1i=kj=1tjFibjii:Fibk+1i+kj=1tjFibji=0 ∀ i : F i b i k + 1 = ∑ j = 1 k t j ⋅ F i b i j ⇔ ∀ i : − F i b i k + 1 + ∑ j = 1 k t j ⋅ F i b i j = 0

用变量 x x 替换上式中的Fibi,上式转化为:

i{1,2,..,k}:f(Fibi)=0 ∀ i ∈ { 1 , 2 , . . , k } : f ( F i b i ) = 0 ,

其中: f(x)=t1x1+t2x2+..tkxk+(xk+1) f ( x ) = t 1 ⋅ x 1 + t 2 ⋅ x 2 + . . t k ⋅ x k + ( − x k + 1 )

也就是说,前k个斐波那契数为这个k+1次函数的k个零点,且最高次项系数为-1。这样的函数显然这个函数是很容易构造的: f(i)=x(xFib1)(xFib2)..(xFibk) f ( i ) = − x ⋅ ( x − F i b 1 ) ⋅ ( x − F i b 2 ) ⋅ . . ⋅ ( x − F i b k )

这个多项式的i次项系数即为 ti t i ,用系数表示法描述多项式,暴力卷积即可通过本题所有数据。

但是我认为这道题可以通过分治FFT进行优化,但对模数M必须进行进一步的约束(或者是使用任意模数的NTT解决,但是可惜我不会啊!!)。

代码

这道题的一种 O(n2) O ( n 2 ) 的做法,其实我觉得并不完美。如果能结合分治套任意模数NTT的话可以优化成 O(nlog2n) O ( n log 2 ⁡ n )

#include <cstdio>
#include <cstring>
typedef long long LLint;
const int maxn=4000+5;

struct vec{
    int len; LLint a[maxn];
    void set(int a0,int a1){
        a[0]=a0;a[1]=a1;len=2;
    }
    void outp(){
        printf("{ ");
        for(int i=0;i<len-1;i++){
            printf("%lld, ",a[i]);
        }
        printf("%lld } ",a[len-1]);
    }
};

void mul(const vec& a,const vec& b,vec& c,LLint M){
    c.len=a.len+b.len-1;
    memset(c.a,0x00,sizeof(LLint)*(c.len+1));
    for(int i=0;i<a.len;i++){
        for(int j=0;j<b.len;j++){
            c.a[i+j] = (c.a[i+j] + a.a[i]*b.a[j]%M)%M;
        }
    }
}

void copy(const vec& a,vec& b){
    b.len=a.len;
    memcpy(b.a,a.a,sizeof(LLint)*(a.len+1));
}

int M;
void operator *=(vec& a,const vec& b){
    vec c; mul(a,b,c,M); copy(c,a);
}

LLint fib[maxn]; vec base,step;

int main(){
    freopen("num.in","r",stdin);
    freopen("num.out","w",stdout);
    int k; scanf("%d%lld",&k,&M);
    fib[0]=fib[1]=1;
    for(int i=2; i<=k+1; i++){
        fib[i] = (fib[i-1] + fib[i-2]) %M;
    }
    base.len=base.a[0]=1;
    for(int i=1; i<=k; i++){
        step.set(-fib[i],1);
        base *= step;
    }
    LLint sum=0;
    for(int i=1;i<=k;i++){
        int p; scanf("%d",&p);
        sum = ((sum - base.a[i-1]*p % M)%M + M) %M;
    }
    printf("%lld\n",sum);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值