zoukankan      html  css  js  c++  java
  • codeforces 816 D. Karen and Test(逆元+思维+组合数)

    题目链接:http://codeforces.com/contest/816/problem/D

    题解:显然一看到这题应该会想到是有什么规律的于是多写几项就会发现偶数列之间是有关系的。

    满足a[i][j]=a[i-2][j]+a[i-2][j+2],于是递推到最后第2列a[2][0],a[2][1]就可以用最早出现的偶数列来求的,最后是加还是减只要看n就行了。

    由于a[2][0]是有几个最早出现的偶数列的奇数项求的,而且这些奇数项选择的次数符合二项式分布(这个可以通过花一下杨辉三角理解一下)。

    #include <iostream>
    #include <cstring>
    #include <cmath>
    #include <cstdio>
    #define mod 1000000007
    using namespace std;
    const int M = 2e5 + 10;
    typedef long long ll;
    ll anum[M] , bnum[M] , up[M] , down[M];
    ll inv(ll a) {
        return a == 1 ? 1 : (ll)(mod - mod / a) * inv(mod % a) % mod;
    }
    //ll C(ll n , ll m)
    //{
    //    if(m < 0)return 0;
    //    if(n < m)return 0;
    //    if(m > n-m) m = n-m;
    //    ll up = 1, down = 1;
    //    for(ll i = 0 ; i < m ; i++){
    //        up = up * (n-i) % mod;
    //        down = down * (i+1) % mod;
    //    }
    //    return up * inv(down) % mod;
    //}//原先利用逆元的算法,但是这里直接求会超时与处理一下up和down就行。
    int main() {
        int n;
        scanf("%d" , &n);
        for(int i = 0 ; i < n ; i++) scanf("%lld" , &anum[i]) , bnum[i] = anum[i];
        if(n == 1) {printf("%lld
    " , anum[0]); return 0;}
        if(n & 1) {
            n--;
            int flag = 1;
            for(int i = 0 ; i < n ; i++) {
                if(flag) anum[i] = (bnum[i] + bnum[i + 1]) % mod;
                else anum[i] = (bnum[i] - bnum[i + 1] + mod) % mod;
                flag ^= 1;
            }
        }
        n = n / 2 - 1;
        ll ans1 = 0 , ans2 = 0;
        up[0] = 1 , down[0] = 1;
        for(int i = 1 ; i <= n / 2 ; i++) up[i] = up[i - 1] * (n - i + 1) % mod , down[i] = down[i - 1] * i % mod;
        for(int i = n / 2 + 1 ; i <= n ; i++) up[i] = up[n - i] , down[i] = down[n - i];
        for(int i = 0 ; i <= n ; i++) {
            ans1 += anum[2 * i] * (up[i] * inv(down[i]) % mod) % mod;
            ans1 %= mod;
            ans2 += anum[2 * i + 1] * (up[i] * inv(down[i]) % mod) % mod;
            ans2 %= mod;
        }
        if(n % 2) ans1 = (ans1 - ans2 + mod) % mod;
        else ans1 = (ans1 + ans2) % mod;
        printf("%lld
    " , ans1);
        return 0;
    }
    
    
  • 相关阅读:
    CentOS Redmine 安装
    [转]Fedora 16 改变启动顺序以及grub2 配置技巧
    impdp/expdp 使用
    Bash 快捷键
    VirtualBox双网卡虚拟机LinuxNAT不能上网
    PRO*C结果集
    Arch Linux 安装配置
    ORA01658: 无法为表空间HS_HIS_DATA中的段创建 INITIAL 区
    XP远程桌面模式下开启ClearType
    制作索引
  • 原文地址:https://www.cnblogs.com/TnT2333333/p/7054283.html
Copyright © 2011-2022 走看看