题意:
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;
}