CF 258B Little Elephant and Elections [dp+组合]

给出1,2,3...m

任取7个互不相同的数a1,a2,a3,a4,a5,a6,a7

一个数的幸运度是数位上4或7的个数

比如244,470幸运度是2。

44434,7276727,4747,7474,幸运度都是4。

求出满足a1,a2,a3,a4,a5,a6,a7这样的前6个数的幸运度之和严格小于第七个数的幸运度排列共有多少种

1.先求出数组t

t[i]代表1-m中幸运度为i的数的个数。

2.有了t数组后,问题变为一个排列组合问题(枚举a7幸运度,求有多少排列满足前6幸运度之和小于a7幸运度,再求和)

t数组怎么得到?

我们定义

d[i][j][0]为
0到从第1数位开始到第i数位(包括第i数位)组成的数中幸运度为j且不含自身(小于自身)的个数

d[i][j][1]为
0到从第1数位开始到第i数位(包括第i数位)组成的数中幸运度为j且包含自身(小于自身)的个数

例如m=14632,对i=2来说,14是自身;对i=3来说,146是自身。

那么

基于dp[i-1][j]转移方式如下

例如m=14632

我们处理好了前两位,到第三位6时

从0开始枚举0,1,2,3,4,5,6,7,8,9

首先所有数(0-5,6,7-9)都可以安插在dp[2][][0]后(显然是dp[3][][0]+=)

如果是小于6的数,还可以安插在dp[2][][1]后(显然是dp[3][][0]+=)

如果是等于6的数,还得有dp[3][][1]+=dp[2][][1]

第二维随情况变化

怎么处理如下的问题(枚举a7幸运度,求有多少排列满足前6幸运度之和小于a7幸运度,再求和)

我们可以拿dfs来解决

首先试着设计这个dfs

状态我们可以这么挂

dfs(int now_lucky_num,int max_lucky_num,int seq)

now_lucky_num:当前的幸运值和

max_lucky_num:幸运值上限(即a7幸运值)

seq:正在处理第几个数(正在处理a几来着)

我们要枚举所有的max_lucky_num从0到9

需要一个cur变量来记录当前的方案数目,一开始cur=t[i]

dfs中,一旦到了第七个数 或者 now_lucky_num>=max_lucky_num,就要return,第二种情况在return之前还得把cur加到最终的答案ans上

在dfs中枚举当前a[seq]的幸运度情况,i从0-9,如果t[i]不为0的话,t[i]--后进入下一个dfs,完成后把t[i]++复原

这样就求得了ans

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
long long f[11][11][2];
long long t[11];
long long n[11];
long long ans=0;
const long long MOD=1e9+7;
long long cur=1;
void dfs(long long now,long long limit,long long number){
    if(now>=limit) return;
    if(number==7){
            ans+=(cur%MOD);
            return;
    }
    for(long long i=0;i<=9;i++){
        if(n[i]){
            long long tmpcur=cur;
            cur*=n[i];
            cur%=MOD;
            n[i]--;
            dfs(now+i,limit,number+1);
            cur=tmpcur;
            n[i]++;
        }
    }
}
int main(){
    #ifndef ONLINE_JUDGE
        freopen("G:/in.txt","r",stdin);
        //freopen("G:/myout.txt","w",stdout);
    #endif
    long long m;
    cin>>m;
    long long tmp=m;
    for(long long i=10;i>=0 && tmp;i--){
        t[i]=tmp%10;
        tmp/=10;
    }
    f[0][0][1]=1;
    for(long long i=1;i<=10;i++){
        for(long long j=0;j<=10;j++){
            for(long long d=0;d<=9;d++){
                if(d<t[i]){
                    f[i][j+(d==4 || d==7)][0]+=f[i-1][j][0];
                    f[i][j+(d==4 || d==7)][0]+=f[i-1][j][1];
                }else if(d==t[i]){
                    f[i][j+(d==4 || d==7)][1]+=f[i-1][j][1];
                    f[i][j+(d==4 || d==7)][0]+=f[i-1][j][0];
                }else{
                    f[i][j+(d==4 || d==7)][0]+=f[i-1][j][0];
                }
            }
        }
    }
    for(long long i=0;i<=10;i++)
        n[i]=f[10][i][0]+f[10][i][1]-(i==0);
    for(long long i=0;i<=9;i++){
        cur=n[i];
        dfs(0,i,1);
    }
    cout<<ans%MOD<<endl;
    return 0;
}
时间: 2024-12-19 11:32:28

CF 258B Little Elephant and Elections [dp+组合]的相关文章

CodeForces 258B Little Elephant and Elections 数位DP

前面先用数位DP预处理,然后暴力计算组合方式即可. #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdlib> #include

[Codeforces 258B &amp; 259 D]Little Elephant and Elections 数位dp+dfs

http://codeforces.com/problemset/problem/258/B 题目大意: 说七个party选择数字(各不相同) 而规定的小象的party选择的数字之中所拥有的数字4和7的个数要比其他六个party拥有的个数之和还要严格多,询问方案数. 如m=7时其余的随意选择至少会拥有一个4或7,与题意矛盾,故方案数为0 m=8时,7 1 2 3 5 6 8是一种合法方案 思路: 由于小象的party选到的数字所含4和7的个数至多和m的位数一样多,则枚举小象的party所含4和7

Little Elephant and Elections CodeForces - 258B

Little Elephant and Elections CodeForces - 258B 题意:给出m,在1-m中先找出一个数x,再在剩下数中找出6个不同的数y1,...,y6,使得y1到y6中数字4和7出现的总次数严格小于x中数字4和7出现的总次数.求方案数. 方法:先数位dp分别预处理出:1到m之间,数字4和7出现的总次数为0到9的数.(总共最多10个数字,第一个最大1,因此4和7出现的总次数最多9次)然后枚举x,再暴力dfs枚举6个数,统计方案数. 问题(细节): 1.(13行)数位

Little Elephant and Elections小象选举

在我正看着roll神的博客的时候发现了自己的错误 #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdlib> #include &

[ACM] hdu 4248 A Famous Stone Collector (DP+组合)

A Famous Stone Collector Problem Description Mr. B loves to play with colorful stones. There are n colors of stones in his collection. Two stones with the same color are indistinguishable. Mr. B would like to select some stones and arrange them in li

CF 366C Dima and Salad [天平DP]

题目大意:n个水果,水果有甜度和卡路里两个属性,选择一些水果,使得甜度之和与卡路里之和比例为k,并且使得甜度之和最大 我们可以定义二维dp,dp[当前游标扫到的个数][平衡度]=当前平衡度下最大的ai和,平衡度定义为ai-bi*k,很巧秒的定义方式,可以节省一维时空. 注意到平衡度可正可负(范围在-10000到10000) 我们可以定义如下 int m[1111][22222] int *d[i]=&m[i][10000] dp[num+1][balance]=max(self,dp[num][

hdu 5396 区间dp+组合

http://acm.hdu.edu.cn/showproblem.php?pid=5396 Problem Description Teacher Mai has n numbers a1,a2,?,anand n?1 operators("+", "-" or "*")op1,op2,?,opn?1, which are arranged in the form a1 op1 a2 op2 a3 ? an. He wants to erase

CF 55D Beautiful numbers (数位DP)

题意: 如果一个正整数能被其所有位上的数字整除,则称其为Beautiful number,问区间[L,R]共有多少个Beautiful number?(1<=L<=R<=9*1018) 思路: 数字很大,不能暴力.但是想要知道一个数是否为Beautiful number时,至少得等到它的所有位都出现吧?不然如何确定其实可以被整除的呢? 分析一下,类似2232和3232等这样的数字,这两个只是出现了2和3而已,他们的lcm都是6,所以有可以压缩统计的地方就是lcm,开一维来存储.接下来考虑

HDU 5434 Peace small elephant 状压dp+矩阵快速幂

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5434 Peace small elephant Accepts: 38 Submissions: 108 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) 问题描述 小明很喜欢国际象棋,尤其喜欢国际象棋里面的大象(只要无阻挡能够斜着走任意格),但是他觉得国际象棋里的大象太凶残了,于是他