• 【loj



    description

    已知函数 (f(k, x)(k, xin mathbb{N}_+)) 满足:

    [f(k, x) = egin{cases} 1 & x = 1\ sum_{i=1}^{x-1}f(k, i) + x^k & x > 1 end{cases} ]

    现在给定 (n, k),求 (f(k, n))

    由于答案很大,你只需计算答案对 (10^9 + 7) 取模后的值。

    problem link。

    solution

    考虑每个 (x^k) 的贡献,可以得到 (f(k, n) = n^k + sum_{i=0}^{n-1}2^{n-i-1}i^k=n^k + 2^{n-1}sum_{i=0}^{n-1}frac{i^k}{2^i})

    (a = frac{1}{2}),尝试求 (F_k(n) = sum_{i=0}^{n-1}a^ii^k)

    通过转下降幂构造错位相减。不妨记 (S_k(n) =sum_{i=0}^{n-1}a^{i}i^{underline k}),则 (F_k(n) = sum_{j=0}^{k}{krace j}S_{j}(n))

    [egin{aligned} S_k(n) &=sum_{i=0}^{n-1}a^{i}i^{underline k}\ aS_k(n) &= sum_{i=0}^{n-1}a^{i+1}i^{underline k} = sum_{i=1}^{n}a^i(i-1)^{underline k} \ (1-a)S_k(n) &= sum_{i=1}^{n}a^i(i^{underline k} - (i-1)^{underline k})-a^nn^{underline k} + a^{0}0^{underline k}\ &= aksum_{i=0}^{n-1}a^ii^{underline {k-1}}-a^nn^{underline k}\ S_k(n) &= frac{ak}{1-a}S_{k-1}(n)-frac{a^nn^{underline k}}{1-a}\ end{aligned} ]

    (k = 0) 时,有 (S_0(n) = sum_{i=0}^{n-1} a^i = frac{1-a^n}{1-a})


    如果硬上任意模数 fft 求斯特林数是过不了的,考虑进一步优化。

    考虑 (S_{k}(n)) 的形式,发现存在最高次数为 (k) 的多项式 (G_k(x)=sum g_ix^i) 满足 (S_k(n)=G_k(n) imes a^n-G_k(0))

    进一步地,存在最高次数为 (k) 的多项式 (G'_k(x)) 满足 (F_k(n)=G'_k(n) imes a^n-G'_k(0))

    可以处理出 (G'_k(i) = alpha_i imes G_{k}'(0)+eta_i) 中的 (alpha_i, eta_i)。再利用如下的 (k+1) 阶差分公式:

    [Delta^{k+1}G'(0)=sum_{i=0}^{k+1}inom{k+1}{i}(-1)^{k+1-i}G'(i)=0 ]

    解出 (G'_k(0)),再拉格朗日插值就可以求 (G'_k(n))

    code

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int MAXN = 1000000;
    const int MOD = int(1E9) + 7;
    const int INV2 = (MOD + 1) >> 1;
    
    inline int add(int x, int y) {x += y; return x >= MOD ? x - MOD : x;}
    inline int sub(int x, int y) {x -= y; return x < 0 ? x + MOD : x;}
    inline int mul(int x, int y) {return (int) (1LL * x * y % MOD);}
    int mpow(int b, int p) {
    	int ret;
    	for(ret=1;p;p>>=1,b=mul(b,b))
    		if( p & 1 ) ret = mul(ret, b);
    	return ret;
    }
    
    char s[MAXN + 5]; int len, n, p, k;
    void read() {
    	scanf("%s%d", s, &k), len = strlen(s);
    	for(int i=0;i<len;i++) {
    		n = (10LL*n + s[i] - '0') % (MOD);
    		p = (10LL*p + s[i] - '0') % (MOD - 1);
    	}
    }
    
    int prm[MAXN + 5], pcnt; bool nprm[MAXN + 5];
    int fct[MAXN + 5], ifct[MAXN + 5], pwk[MAXN + 5];
    void init() {
    	fct[0] = 1; for(int i=1;i<=k+3;i++) fct[i] = mul(fct[i - 1], i);
    	ifct[k+3] = mpow(fct[k+3], MOD - 2);
    	for(int i=k+2;i>=0;i--) ifct[i] = mul(ifct[i + 1], i + 1);
    	
    	pwk[1] = 1;
    	for(int i=2;i<=k+3;i++) {
    		if( !nprm[i] ) prm[++pcnt] = i, pwk[i] = mpow(i, k);
    		for(int j=1;i*prm[j]<=k+3;j++) {
    			nprm[i*prm[j]] = false;
    			pwk[i*prm[j]] = mul(pwk[i], pwk[prm[j]]);
    			if( i % prm[j] == 0 ) break;
    		}
    	}
    }
    
    int lf[MAXN + 5], rf[MAXN + 5];
    int gety(int x, int k, int *y) {
    	lf[0] = 1; for(int i=1;i<=k;i++) lf[i] = mul(lf[i - 1], sub(x, i));
    	rf[k + 1] = 1; for(int i=k;i>=1;i--) rf[i] = mul(rf[i + 1], sub(x, i));
    	
    	int ret = 0;
    	for(int i=1;i<=k;i++) {
    		int coef = mul(mul(lf[i - 1], rf[i + 1]), mul(ifct[i - 1], ifct[k - i]));
    		if( (k - i) & 1 ) ret = sub(ret, mul(coef, y[i]));
    		else ret = add(ret, mul(coef, y[i]));
    	}
    	return ret;
    }
    
    int a[MAXN + 5], b[MAXN + 5], g[MAXN + 5];
    int main() {
    	read(), init();
    	
    	a[0] = 1;
    	for(int i=1;i<=k+1;i++)
    		a[i] = mul(2, a[i - 1]), b[i] = mul(2, add(b[i - 1], pwk[i - 1]));
    	
    	int A = 0, B = 0;
    	for(int i=0;i<=k+1;i++) {
    		int del = mul(ifct[i], ifct[k + 1 - i]);
    		if( (k + 1 - i) & 1 )
    			A = sub(A, mul(del, a[i])), B = sub(B, mul(del, b[i]));
    		else A = add(A, mul(del, a[i])), B = add(B, mul(del, b[i]));
    	}
    		
    	g[0] = mul(mpow(A, MOD - 2), MOD - B);
    	for(int i=1;i<=k+1;i++) g[i] = add(mul(a[i], g[0]), b[i]);
    	
    	int ans = sub(mul(mpow(INV2, p), gety(n, k + 1, g)), g[0]);
    	printf("%d
    ", add(mul(mpow(2, p+(MOD-1)-1), ans), mpow(n, k)));
    }
    

    details

    lca给的solution 是根据递推式直接构造了一个多项式,然后转成了常系数线性递推(虽然最后算法的形式差不多)。

    不过感觉 (sum_{i=0}^{n-1}a_ii^k) 这个形式更普遍一些(不清楚我乱说的)?

  • 相关阅读:
    C# 学习之路--百度网盘爬虫设计与实现(一)
    Codeforces Round #359 div2
    Codeforces Round #360 div2
    Codeforces Round #361 div2
    Codeforces Round #329 div2
    Codeforces Round #328 div2
    Codeforces Round #327 div2
    【招聘App】—— React/Nodejs/MongoDB全栈项目:个人中心&退出登录
    【招聘App】—— React/Nodejs/MongoDB全栈项目:信息完善&用户列表
    【招聘App】—— React/Nodejs/MongoDB全栈项目:登录注册
  • 原文地址:https://www.cnblogs.com/Tiw-Air-OAO/p/13227326.html
Copyright © 2020-2023  润新知