zoukankan      html  css  js  c++  java
  • JZOI 4305. 【NOIP2015模拟11.3晚】七十和十七

    洛谷AC通道!

    设$f[i]$为长度为$i$的序列(不是排列)中计数器的大小。假设现在已知$f[i-1]$

    那么第$i$位与前面的相对大小关系一共有i种

    1.第$i$位相对大小为i,对计数器没有任何影响,直接转移 $f[i]=f[i-1]$

    2.第$i$位相对大小小于$i$ (即$1~i-1$),设为$j$,那么计数器的值就需要增加$2^{j-1}$ (可以拿几个数试一下),对于前$i-1$个数,他们的顺序有$(i-1)!$种,所以$ f[i]=f[i-1]+2^{j-1}*(i-1)!$

    综上,

    $f[i]=f[i-1]+(f[i-1]+2^{1-1}*(i-1)!)+(f[i-1]+2^{2-1}*(i-1)!)+(f[i-1]+2^{3-1}*(i-1)!)...+(f[i-1]+2^{i-1-1}*(i-1)!)$

    发现$2$的多少次方是一个等比数列,可以直接用前$i-1$项和公式求出来,剩下$i$个$f[i-1]$相加

    最终得到$f[i]=f[i-1]*i+(2^{i-1}-1)*(i-1)!$

    答案即为$f[n]/n!$

    #include <bits/stdc++.h>
    using namespace std;
    #define N 100010
    #define ll long long 
    const int mod = (int)1e9 + 7;
    
    inline int read(){
        int x = 0, s = 1;
        char c = getchar();
        while(!isdigit(c)){
            if(c == '-') s = -1;
            c = getchar();
        }
        while(isdigit(c)){
            x = x * 10 + (c ^ '0');
            c = getchar();
        }
        return x * s;
    } 
    
    ll qpow(ll a, ll b){
        ll sum = 1;
        while(b){
            if(b & 1) sum = (sum * a) % mod;
            a = (a * a) % mod;
            b >>= 1;
        }
        return sum;
    }
    
    ll f[N];
    ll n;
    
    
    int main(){
    //    freopen("seventeen10.in", "r", stdin);
    //    freopen("seventeen10.out", "w", stdout);
        n = read();
        ll num = 1, tot = 1;
        for(ll i = 1; i <= n; i++){
            f[i] = (f[i - 1] * i % mod + (tot - 1) * num % mod) % mod;
            tot = (tot << 1) % mod;
            num = (num * i) % mod;
        } 
        cout << f[n] * qpow(num, mod - 2) % mod << endl;
        return 0;
    }

    部分转载于大佬的博客

  • 相关阅读:
    定制专属于你的系统安装镜像
    COBBLER无人值守安装
    KICKSTART无人值守安装
    关系型数据库与非关系型数据库的区别
    MooseFS 分布式存储
    GlusterFS 存储
    Crush 算法以及PG和PGP调整经验
    对象存储、块存储、文件存储的差异
    Ceph 概述和理论
    Go之gob包的使用
  • 原文地址:https://www.cnblogs.com/wondering-world/p/13396446.html
Copyright © 2011-2022 走看看