列表

详情


NC15708. 细胞

描述

Shero在秘密基地有一个专门研究活骸化的实验室。
实验室里面有一排从0开始标号的培养皿,初始的时候只有0号培养皿中有1个细胞。
因为是虚拟实验,所以可以认为培养皿有无限个。
Shero观察发现,来自异世界的细胞分裂速度似乎要比的一般的细胞迅速得多:
具体来说,第n天第k个培养皿中会有2k x C(n,k)个细胞(异世界的细胞当然有能力到处跑啦
为了找到活骸化的原因,Shero给出了一个参数m,现在他想知道在第n天对于每一个0<=i<2m,所有下标mod 2m为i的培养皿中的细胞数量总和是多少

输入描述

第一行两个正整数n,m

输出描述

设ans[i]表示下标mod 2^m为i的培养皿中的细胞总数
一行一个正整数输出 mod 998244353的值

示例1

输入:

4 2

输出:

3738937

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 877ms, 内存消耗: 12892K, 提交时间: 2018-11-15 14:56:41

#include <cstdio>
#include <algorithm>
#include <cmath>

using namespace std;

typedef long long ll;

const int maxn = 4000010;
const ll mod = 998244353;
const ll g = 3;

int R[maxn], BIT;

ll Pow(ll x, ll y){
	ll res = 1;
	for( ; y; x = (x * x) % mod, y >>= 1) if(y & 1) res = (res * x) % mod;
	return res;
}

ll ni(ll x){
	return Pow(x, mod-2);
}

void ntt(ll *a, int n, int inv){
	if(R[n-1] != n-1) for(int i = 0; i < n; i ++) R[i] = (R[i>>1]>>1) | ((i&1)<<(BIT-1));
	for(int i = 0; i < n; i ++) if(i < R[i]) swap(a[i], a[R[i]]);
	for(int i = 1; i < n; i <<= 1){
		ll mi = inv == 1 ? Pow(g, (mod-1)/(2*i)) : ni(Pow(g, (mod-1)/(2*i)));
		for(int j = 0; j < n; j += (i<<1)){
			ll x = 1;
			for(int k = 0; k < i; k ++, x = (x * mi) % mod){
				ll t1 = a[j+k], t2 = (x * a[j+k+i]) % mod;
				a[j+k] = (t1 + t2) % mod, a[j+k+i] = (t1 - t2) % mod; 
			}
		}
	}
}

ll n, m;
ll a[maxn], res;
int main(){
	scanf("%lld%lld", &n, &m);
	BIT = m, m = (1<<m);
	for(int i = 0; i < m; i ++) a[i] = Pow(2*Pow(g, (i*(mod-1))/m) + 1, n);
	ntt(a, m, -1);
	for(int i = 0; i < m; i ++) a[i] = (a[i] * ni(m)) % mod;
	for(int i = 0; i < m; i ++) res = (res + a[i] * Pow(2222303LL, i)) % mod;
	printf("%lld\n", (res%mod + mod) % mod);
	return 0;
} 

C++(g++ 7.5.0) 解法, 执行用时: 513ms, 内存消耗: 12604K, 提交时间: 2022-11-02 12:32:02

#include<cstdio>
#include<algorithm>
const int p=119<<23|1;
constexpr long long fp(long long a,long long b)
{
	long long ans=1;
	while(b)
	{
		if(b&1)ans=(ans*a)%p;
		a=(a*a)%p,b>>=1;
	}
	return ans;
}
constexpr int g=3,ig=fp(3,p-2);
class _FNTT
{
	int r[1<<20],lim;
public:
	void init(int l)
	{
		lim=1<<l;for(int i=1;i<lim;i++)r[i]=r[i>>1]>>1|(i&1)<<l-1;
	}
	void operator()(long long*a,int type)
	{
		for(int i=0;i<lim;i++)if(i<r[i])std::swap(a[i],a[r[i]]);
		for(int mid=1;mid<lim;mid<<=1)
		{
			long long on=fp(type==1?g:ig,(p-1)/mid>>1);
			for(int j=0;j<lim;j+=mid<<1)
			{
				long long o=1;
				for(int k=0;k<mid;k++,o=o*on%p)
				{
					long long x=a[j+k],y=a[j+k+mid]*o%p;
					a[j+k]=(x+y)%p,a[j+k+mid]=(x-y+p)%p;
				}
			}
		}
		if(type==-1)
		{
			long long inv=fp(lim,p-2);
			for(int i=0;i<lim;i++)a[i]=a[i]*inv%p;
		}
	}
}NTT;
long long a[1<<20];
int main()
{
	long long n;int m;scanf("%lld%d",&n,&m);
	const long long mul=2222303ll;long long ans=0;
	a[0]=1,a[1]=2;NTT.init(m);m=1<<m;
	NTT(a,1);for(int i=0;i<m;i++)a[i]=fp(a[i],n);
	NTT(a,-1);for(int i=m-1;i>=0;i--)ans=(ans*mul+a[i])%p;
	printf("%lld",ans);
	return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 530ms, 内存消耗: 10828K, 提交时间: 2018-04-21 07:23:07

#include<bits/stdc++.h>
using namespace std;
#define N 1100000
#define mo 998244353
int Pow(int x,long long y){
	int res=1;
	while (y>0){
		if (y&1){
			res=1LL*res*x%mo;
		}
		y>>=1;
		x=1LL*x*x%mo;
	}
	return res;
}
int A[N],Rev[N],n,w[N];
void DFT(int *A,int p){
	int i,j,k;
	for (i=0;i<n;i++){
		if (i<Rev[i]){
			swap(A[i],A[Rev[i]]);
		}
	}
	w[0]=1;
	for (i=1;i<n;i<<=1){
		int wn=Pow(3,mo-1+p*(mo-1)/(i<<1));
		for (j=i-2;j>=0;j-=2){
			w[j]=w[j>>1];
			w[j+1]=1LL*wn*w[j]%mo;
		}
		for (j=0;j<n;j+=(i<<1)){
			int *f=A+j,*g=A+j+i;
			for (k=0;k<i;k++){
				int x=1LL*w[k]*g[k]%mo;
				g[k]=(f[k]-x+mo)%mo,f[k]=(f[k]+x)%mo;
			}
		}
	}
}
int main(){
	long long t;
	int m,i;
	scanf("%lld%d",&t,&m);
	n=1<<m;
	for (i=0;i<n;i++){
		Rev[i]=(Rev[i>>1]>>1)|((i&1)<<(m-1));
	}
	A[0]=1,A[1]=2;
	DFT(A,1);
	for (i=0;i<n;i++){
		A[i]=Pow(A[i],t);
	}
	DFT(A,-1);
	int Ans=0,now=1;
	for (i=0;i<n;i++){
		Ans=(Ans+1LL*A[i]*now%mo)%mo;
		now=1LL*now*2222303%mo;
	}
	printf("%lld\n",1LL*Ans*Pow(n,mo-2)%mo);
	return 0;
}

上一题