2017 ACM-ICPC 西安赛区 网络赛 F. Trig Function 【规律题】


Trig Function

TimeLimit: 2000/1000 MS (Java/Others)    Memory Limit:32768/32768 K (Java/Others)
Total Submission(s): 714    Accepted Submission(s): 206

Problem Description

f(cos(x))=cos(n∗x) holds for all x.

Given two integersn and m , you need to calculate the coefficient of x^m​​ in f(x), modulo 998244353

   

Input

Multiple testcases (no more than 100).

Each test casecontains one line consisting of two integers n and m.

1≤n≤109,0≤m≤104

   

Output

Output the answerin a single line for each test case.

  

Sample Input

2 0

2 1

2 2

 

Sample Output

998244352

0

2



【题意】


给出一个函数,代入n,m后求出xm的系数,并取膜输出。


【思路】


我们先尝试把cos(nx)化为cos(x)的形式,然后把cos(x)用x代换,就可以得到f(x)=...的形式,然后就能得到所求的系数了。


那么我们如何把cos(nx)化为cos(x)的形式呢。


其实可以尝试着暴力写出前几项的形式。如下图:


由写出的式子,我们可以发现以下几点:


  1. 当m大于n时,答案显然为0。
  2. 当n为奇数且m为偶数或n为偶数且m为奇数时答案显然为0。
  3. 当n为奇数,且m为1时,答案的绝对值为n。
  4. 当n为偶数,且m为0时,答案的绝对值为1。
  5. 其余情况答案的绝对值均为【 n * (n-m+2) * (n-m+4) * ... * (n+m-4) * (n+m-2) 】/(m!)。(注意逆元的运用)
  6. 上面出现绝对值的情况,3和4 当(n/2)%2 == 0 时符号为正,否则为负;5 当((n-m)/2)%2 == 0时,符号为正,否则符号为负。


依照这个规律分类讨论一下即可。


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

typedef long long ll;
const int maxn = 100005;
const ll mod = 998244353;
const int INF = 0x3f3f3f3f;
const double eps = 1e-9;

int n,m;
int a[maxn];

ll fast_mod(ll a,ll b,ll Mod)
{
    ll ans=1;
    a%=Mod;
    while(b)
    {
        if(b&1)
            ans=(ans*a)%Mod;
        b>>=1;
        a=(a*a)%Mod;
    }
    return ans;
}


ll solve(ll n,ll m)
{
    if(n&1)
    {
        if(m%2==0) return 0;
        if(m==1)
        {
            if((n/2)%2==0) return n;
            return -n;
        }
    }
    else
    {
        if(m&1) return 0;
        if(m==0)
        {
            if((n/2)%2==0) return 1;
            return -1;
        }
    }
    ll ans=1;
    for (int i=n-m+2; i<=n+m-2; i+=2)
    {
        ans=(ans*i)%mod;
    }
    ans=(ans*n)%mod;
    ll temp=1;
    for(int i=1;i<=m;i++)
    {
        temp=(temp*i)%mod;
    }
    ans=(ans*fast_mod(temp,mod-2,mod))%mod;  //求逆元
    int flag=(((n-m)/2)%2==0)?1:-1;
    return flag*ans;
}


int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        if(m>n)
        {
            puts("0");
            continue;
        }
        ll ans=solve(n,m);
        ans=(ans+mod)%mod;
        printf("%lld\n",ans);
    }
    return 0;
}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值