zoukankan      html  css  js  c++  java
  • 一道题

    Description

    仅包含4或7的数被称为幸运数。
    一个序列的子序列被定义为从序列中删去若干个数,剩下的数组成的新序列。
    两个子序列被定义为不同的当且仅当其中的元素在原始序列中的下标的集合不
    相等。对于一个长度为N的序列,共有2^N个不同的子序列。(包含一个空序列)。
    一个子序列被称为不幸运的,当且仅当其中不包含两个相同的幸运数。
    对于一个给定序列,求其中长度恰好为K的不幸运子序列的个数,答案mod 10^9+7 输出。

    Solution

    此题堪称大型翻车现场, 有好几个人读错题. 一个人丢了20分.

    只有我出了好几种错误.(数据太水了还能让我拿到分)

    发现一共有(2^1 + 2^2 + 2 ^ 3+cdots)种幸运数字, 也就是说(10^9)以内的数只有(1023)种幸运数字.(坑死一个叫zzx的人)
    将给定的(n)个数分成幸运数和非幸运数, 统计出每种幸运数字出现的次数.

    (f(i,j))表示前(i)种幸运数字选出(j)个作为子序列的方案数.

    转移方程

    [f(i,j)=f(i-1,j)+f(i-1,j-1)cdot S_i ]

    最后将非幸运数字加进去.
    答案就是
    (sum_{i=0}^kf(m, i){nchoose m - i})

    Code

    #include <map>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int N = 100005;
    const int mod = 1e9 + 7;
    inline long long Pow(int a, int b) {
        long long res = 1, base = a;
        while (b) {
            if (b & 1) 
                res = res * base % mod;
            base = base * base % mod;
            b >>= 1;
        }
        return res;
    }
    inline long long Inv(int a) {
        return Pow(a, mod - 2);
    }
    long long fff[N];
    inline long long F(int n) {
        if (fff[n]) return fff[n];
        fff[0] = 1;
        for (int i = 1; i <= 100000; i += 1)
            fff[i] = fff[i - 1] * i % mod;
        return fff[n];
    }
    inline long long C(int n, int m) {
        return (F(n) * Inv(F(m)) % mod) * Inv(F(n -m)) % mod;
    }
    inline bool Judge(int p) {
        while (p) {
            if (p % 10 != 4 and p % 10 != 7) return false;
            p /= 10;
        }
        return true;
    }
    
    int tot = 0;
    int S[N];
    long long f[2][N];
    map<int, int> M;
    int main () {
        freopen("lucky.in", "r", stdin);
        freopen("lucky.out", "w", stdout);
        int n, k;
        scanf("%d%d", &n, &k);
        int size = 0, tot = 0;
        for (int i = 0, temp; i < n; i += 1) {
            scanf("%d", &temp);
            if (Judge(temp)) {
                if (not M[temp]) M[temp] = ++tot;
                S[M[temp]] += 1;
            } else size += 1;
        }
        if (size + tot < k) {
            printf("%d
    ", 0);
            return 0;
        }
        f[0][0] = 1;
        long long *F = f[1], *G = f[0];
        for (int i = 1; i <= tot; i += 1) {
            for (int j = 0; j <= tot; j += 1) {
                F[j] = ((j ? (G[j - 1] * S[i]) % mod : 0) + G[j]) % mod;
                F[j] %= mod;
                if (not F[j]) break;
            }
            swap(F, G);
        }
        long long res = 0;
        for (int i = 0; i <= k; i += 1) {
            if (k - i <= size) 
                res = (res + (G[i] * C(size, k - i) % mod)) % mod;
        }
        printf("%d
    ", res);
        return 0;
    }
    
  • 相关阅读:
    准确且巧妙的躲过了正确答案;
    百思不得其解,终得妙笔生花;
    考后小反思
    第一次接触oi知识对其分析。
    0515比赛感慨
    变量问题——赋值问题
    oi集训第七天感慨
    OI集训第五天总结(似乎是第一个正经题目)
    OI萌新第四天的渺(考)小(试)发(总)言(结)
    刚刚入Oi坑两天的萌新对于今天的吐槽
  • 原文地址:https://www.cnblogs.com/qdscwyy/p/9889069.html
Copyright © 2011-2022 走看看