1. 程式人生 > >2018QBXT刷題遊記(3)

2018QBXT刷題遊記(3)

【2018QBXT刷題遊記】

Day1 TEST1

T3 difer

【問題描述】
在數學中, 對光滑函式求微分是一種常見的操作。 在實際應用中, 一些函式沒有解析形式, 通常會從函式上取若干個點,用這些點來近似地表示這個函式。
現在有一個函式\(f(x)\),我們在函式上取 \(n\)個值 \(f(1),f(2),…,f(n)\)。對函式 \(f(x)\)取微分得到函式 \(f’(x)\)。我們近似地認為 \(f’(i)=f(i)-f(i-1)\)
同理,對 \(f’(x)\)求微分可以得到 \(f’’(x)\),我們近似地認為 \(f’’(i)=f’(i)-f’(i-1)\)。(注意這裡的 f’(i)和 f’(i-1)本身就是我們求的近似值)。
函式 \(f’(x)\)

被稱為一階微分, \(f’’(x)\)被稱為二階微分。如果對函式 \(f(x)\)連續做 \(m\)次微分操作,得到的函式被稱為 \(m\) 階微分。 特殊地, \(f(x)\)可以被認為是自身的0階微分。
\(f[m](x)\)表示 \(f(x)\)\(m\) 階微分,我們認為對任意自然數 \(m\),有 \(f[m](0)=0\)
在計算近似值時,直接使用這條性質。

輸入的是 \(f(1),f(2),…,f(n)\)
\(f[0](x)=f(x), x=1,2,…,n\)
\(f[i](0)=0, i=0,1,…m\)
\(f[i](x)=f[i-1](x)-f[i-1](x-1), x=1,2,…,n, i=1,2,…,m\)


輸出的是 \(f[m](x) , x=1,2,…,n\)
【輸入格式】
第一行兩個數 \(n, m\)
第二行 n 個數 \(f(1),f(2),…,f(n)\)
【輸出格式】
輸出 \(n\) 行, 第 \(x\) 行是 \(f[m](x)\)
結果對 \(100007\) 取模
【樣例輸入】
3 2
6 7 8
【樣例輸出】
6
100002
0
【資料規模和約定】
對於 30%的資料, \(m<=1000\)
對於 60%的資料,\(m<=10^6\)
對於 100%的資料, \(n<=1000, m<=10^9, 0<=f(i)<100007\)

【分析】

可以發現:
\[f[m](i)=\sum_{j=0}^i (-1)^j·C(m,j)·f[0](i-j) \]

需要注意的是,模數不是質數,所以不能用盧卡斯定理。

一開始以為是擴充套件盧卡斯,後來發現這題資料比較小,沒必要這麼麻煩。對分子和分母分解質因數即可。

#include<iostream>
#include<cstdio>
using namespace std;
#define MOD 100007
#define MAXN 1007
#define ll long long
int n,m,fenzi[MAXN][MAXN],fenmu[MAXN][MAXN],shengyu[MAXN];
int f[MAXN];//初始 
int ans[MAXN]; 
int add(int x,int y){
    x+=y;
    if(x>=MOD)x-=MOD;
    return x;
}
int jian(int x,int y){
    x-=y;
    if(x<0)x+=MOD;
    return x;
}
int mul(int x,int y){
    ll ret=x;
    ret*=y;
    ret%=MOD;x=ret;
    return x;
}

int main(){
    freopen("difer.in","r",stdin);
    freopen("difer.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&f[i]);
    for(int i=1;i<=n&&i<=m;i++){//對分子質因數分解 
        fenzi[i][0]=m+1-i;
        for(int j=2;j<=n;j++){
            while(fenzi[i][0]%j==0){//保證分解出的一定是質數 
                fenzi[i][0]/=j;
                fenzi[i][j]++;
            }
        }
        fenzi[i][0]%=MOD;
    }
    for(int i=1;i<=n&&i<=m;i++){//對分母質因數分解 
        fenmu[i][0]=i;
        for(int j=2;j<=n;j++){
            while(fenmu[i][0]%j==0){
                fenmu[i][0]/=j;
                fenmu[i][j]++;
            }
        }
    }ans[0]=1;
    for(int i=1;i<=n&&i<=m;i++){
        ans[i]=1;
        for(int j=1;j<=i;j++)ans[i]=mul(ans[i],fenzi[j][0]);
        for(int j=2;j<=n;j++){
            shengyu[j]+=(fenzi[i][j]-fenmu[i][j]);
        }
        for(int j=2;j<=n;j++){
            for(int k=1;k<=shengyu[j];k++)ans[i]=mul(ans[i],j);
        }
        if(i&1)ans[i]=jian(0,ans[i]);
    }
    for(int i=1;i<=n;i++){
        int ret=0;
        for(int j=0;j<=i&&j<=m;j++)ret=add(ret,mul(f[i-j],ans[j]));
        printf("%d\n",ret);
    }
    return 0;
}