CQOI2015多项式题解 (NKOJ3252)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CQOI2015多项式题解 (NKOJ3252)相关的知识,希望对你有一定的参考价值。

再次感谢Wikipedia提供公式支撑。

题面:Here

这道题其实很水,坑点在高精度。

给定 $F(x)=\sum^n_{k=0}a_kx^k=\sum^n_{k=0}b_k(x-t)^k$, 求给定$b_m$。

想都不想就是$F(x)$在$x=t$处的Taylor展开

\begin{align}F(x)=\sum^n_{k=0}\frac{F^{(k)}(t)}{k!}(x-t)^k\end{align}

易知$b_m=\frac{F^{(m)}\ \ (t)}{m!}$, 而容易得到$\frac{F^{(m)}\ \ (t)}{m!}=\sum^{n-m}_{k=0}(^{m+k}_{k})a_{m+k}t^k$,

至于{$a_k$},因为$mod\ 3389$意义下的数是有限的,显然有循环节,跑一遍就知道$a_k=a_{k\ mod\ 3388}$, 剩下的就只剩下写个高精度乱搞了。

(然而自己过于菜,写个高精度调一下午。。。

(分段一定1e9!!!

Code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int a;
const int MOD=1e9;
struct Big {
	ll S[10000],T,cur;
	void Input() {
		string s;cin>>s;int i,t,l=s.size();
		for(i=0;i<l;i++)
			t=(l-i-1)/9,S[t]=S[t]*10+s[i]-48,T=T*10+s[i]-48,T%=3388;
		cur=(l-1)/9;while(cur>0&&S[cur]==0) cur--;
	}
	void Divide(int k) {
		for(int i=cur;i>0;i--) {
			S[i-1]+=S[i]%k*MOD;S[i]/=k;
			if(S[cur]==0) cur--;
		} S[0]/=k;
	}
	void Add(int k) {
		S[0]+=k;int i=0;
		while(S[i]>=MOD) S[i+1]+=S[i]/MOD,S[i++]%=MOD;
		if(S[cur+1]) cur++;
	}
	void Add(const Big& o) {
		int i,r=max(o.cur,cur);
		for(i=0;i<=r;i++) {
			S[i]+=o.S[i];
			if(S[i]>=MOD) S[i+1]+=S[i]/MOD,S[i]%=MOD;
		} cur=r+5;while(cur>0&&S[cur]==0) cur--;
	}
	void Multiply(const Big& o,Big& E) {
		int i,j;memset(&E,0,sizeof(E)); 
		for(i=0;i<=cur;i++)
		for(j=0;j<=o.cur;j++) {
			E.S[i+j]+=S[i]*o.S[j];
			if(E.S[i+j]>=MOD) {
				E.S[i+j+1]+=E.S[i+j]/MOD;
				E.S[i+j]%=MOD; 
			}
		}
		E.cur=cur+o.cur+5;
		while(E.S[E.cur]==0) E.cur--;
	}
	void Print() {
		printf("%lld",S[cur]);
		ll i,k;
		for(i=cur-1;i>=0;i--) {
			k=MOD/10;
			while(k>S[i]) putchar(‘0‘),k/=10;
			if(k) printf("%lld",S[i]);
		}
	}
} N,M,J[10],T[2],R[2],Q,P[2],ANS;
int K,k,i,j;
int main() {
	N.Input();J[1].Input();M.Input();K=N.T-M.T;K+=K<0?3388:0;
	a=1;for(i=1;i<=M.T;i++) a=(1234*a+5678)%3389;
//	cout<<N.T<<‘ ‘<<M.T<<endl;
	ANS.Add(a);T[0].S[0]=1;
//	N.Print();puts("");
//	J[1].Print();puts("");
//	M.Print();puts("");
	for(k=1;k<=K;k++) {
		M.Add(1);
//		M.Print();puts("");
		T[k-1&1].Multiply(M,T[k&1]);
//		T[k].Print();
		a=(1234*a+5678)%3389;
		Q.S[0]=a;
		T[k&1].Divide(k);//T[k].Print();
		T[k&1].Multiply(Q,R[k&1]);
		if(k<K) J[k].Multiply(J[1],J[k+1]);
		J[k].Multiply(R[k&1],P[k&1]);
		ANS.Add(P[k&1]);
	}
	ANS.Print();
//	N.Input();M.Input();
//	N.Multiply(M,ANS);
//	ANS.Print(); 
}

代码风格过于丑,请自动忽略各种调试语句。

 

以上是关于CQOI2015多项式题解 (NKOJ3252)的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ3930:[CQOI2015]选数——题解

BZOJ3932:[CQOI2015]任务查询系统——题解

NKOJ2319 奇怪的班级 题解

BZOJ2716 & NKOJ2739:[Violet 3]天使玩偶——题解

[题解]NKOJ 3102取数(乱搞)

[bzoj3932][CQOI2015]任务查询系统-题解[主席树][权值线段树]