2017 ACM-ICPC 西安網絡賽 Trig Function

題意:

f(cos(x))=cos(n∗x) 對任意x都成立,問x^m在f(x)中的係數是多少?

思路:

由於網絡賽,馬上想到了傅里葉展開,或者泰勒展開,發現好像都不行

乾脆直接百度到倍角公式



lucas定理可以求出較大的組合數,這裏求和,i+1的項可以由第i項簡單的得到,不必每次求一次組合數

#include<bits/stdc++.h>
using namespace std;
typedef long long  ll;
const int mo=998244353;
const long long N=998244353;
ll qpow(ll a,ll k)
{
	ll ans=1;
	while(k)
	{
		if(k&1)
		ans=(ans*a)%mo;
		a=(a*a)%mo;
		k>>=1; 
	}
	return ans;
 } 
ll C(ll a,ll b)
{
	if(a<b)
	return 0;
	if(b>a-b)
	b=a-b;
	ll up=1,down=1;
	for(ll i=0;i<b;i++)
	{
		up=up*(a-i)%mo;
		down=down*(i+1)%mo;
	}
	return up*qpow(down,mo-2)%mo;
}
long long inv[6005000],fac[6005000];
void init()  
{  
    inv[0] = fac[0] = inv[1] = fac[1] = 1;  
    for(int i = 1; i < 6000000+10; i++)  
    fac[i] = fac[i - 1] * i % N;  
    for(int i = 2; i < 6000000+10; i++)  
    inv[i] = (N - (N / i)) * inv[N % i] % N;//lucas?????  
    for(int i = 1; i < 6000000+10; i++)  
    inv[i] = inv[i - 1] * inv[i] % N;   
}   
ll Comb(int n, int m)//???? C n,m   
{  
    return (fac[n] * inv[m] % N) * inv[n - m] %N;   
}  
ll lucas(ll a,ll b)
{
	if(a<b||a<0||b<0)
	return 0;
	if(b==0)
	return 1;
	if(a<=6000000)
	return Comb(a,b);
	return C(a%mo,b%mo)*lucas(a/mo,b/mo)%mo; 
}
int main()
{
	int n,m,i;
	init();
	while(~scanf("%d %d",&n,&m))
	{
		if(((n-m)&1)||n<m)
		printf("0\n");
		else
		{
			long long ans=0;
			
			long long ax,bx,a1,a2,b1,b2;
			
			i=(n-m)/2;
			ax=lucas(n,2*i);
			bx=1;
			ans=((ax*bx)%mo+mo)%mo;
	      
			a1=n-2*i+1;
			b1=2*i;
			
			a2=i;
			b2=0;
			
			i++;
			for(;2*i<=n;i++)
			{  
				a1--;
				ax=ax*a1%mo;
				a1--;
				ax=ax*a1%mo;
				b1++;
				ax=ax*qpow(b1,N-2)%mo;
				b1++;
				ax=ax*qpow(b1,N-2)%mo;
				a2++;
				bx=bx*a2%mo;
			    b2++;
			    bx=bx*qpow(b2,N-2)%mo;
				ans=(ans+(ax*bx)%mo+mo)%mo;	
			}
			i=(n-m)/2;
			if(i&1) ans=-ans;
			ans=(ans%mo+mo)%mo;
				printf("%lld\n",ans);
		}
	}
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章