BZOJ 1974 [Sdoi2010]auction 代码拍卖会 | 51nod 1261 上升数

原创 2016年06月22日 20:59:36

题目:
http://www.lydsy.com/JudgeOnline/problem.php?id=1974
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1261

题意:
一个10进制表示的正整数,如果从左到右,每一位的数字都不小于前一位的数字,则被称为上升数。
给出正整数NK,求有多少个长度恰好为N的上升数是K的倍数,答案对999911659取模。
N1018,K500

题解:
上升数可以拆成不超过9个类似10k19的数字的和,这些数字(1,11,111,1111,)在模K意义下的值有O(K)种取值,可以将这些数分成O(K)组,进行分组背包计数。
f[i][j][k]表示前i组里选j个数的和在模K意义下是k的方案数,由于同一组里选m个数组成可重集的方案数是(X1+mm),其中X表示组里不同数字的个数,所以转移是枚举当前组里选多少个数进行转移。
注意10N19至少要选1个,所以将它从上面的计数里排除,最后枚举它的数量,再配合之前计数的结果进行计数即可。
时间复杂度O(102K2),数组滚动后空间复杂度O(10K)
注意K=1的情况。

代码:

#include <cstdio>
typedef long long LL;
const int maxm = 510, maxd = 10, mod = 999911659;
LL n;
int m, a[maxm], pos[maxm], s[maxm], val, inv[maxd], f[maxd][maxm], ans;
int main()
{
    scanf("%lld%d", &n, &m);
    a[1] = 1 % m;
    pos[a[1]] = 1;
    for(int i = 2; i <= m + 1; ++i)
    {
        a[i] = (a[i - 1] * 10 + 1) % m;
        if(pos[a[i]])
        {
            int beg = pos[a[i]], end = i, len = end - beg;
            for(int j = 1; j < beg && j <= n; ++j)
                ++s[a[j]];
            for(int j = 0; j < len && beg + j <= n; ++j)
                s[a[beg + j]] = (s[a[beg + j]] + (n - beg - j) / len + 1) % mod;
            val = n < beg ? a[n] : a[beg + (n - beg) % len];
            --s[val];
            if(s[val] < 0)
                s[val] += mod;
            break;
        }
        pos[a[i]] = i;
    }
    inv[1] = 1;
    for(int i = 2; i < maxd; ++i)
        inv[i] = mod - mod / i * (LL)inv[mod % i] % mod;
    f[0][0] = 1;
    for(int i = 0; i < m; ++i)
    {
        if(!s[i])
            continue;
        for(int j = maxd - 1; j > 0; --j)
        {
            int coeff = 1;
            for(int k = 1; k <= j && coeff; ++k)
            {
                coeff = (LL)coeff * (s[i] - 1 + k) % mod * inv[k] % mod;
                for(int o = 0; o < m; ++o)
                    f[j][(o + k * i) % m] = (f[j][(o + k * i) % m] + (LL)coeff * f[j - k][o]) % mod;
            }
        }
    }
    for(int i = 1; i < maxd; ++i)
    {
        int res = val * i % m;
        if(res)
            res = m - res;
        for(int j = 0; i + j < maxd; ++j)
        {
            ans += f[j][res];
            if(ans >= mod)
                ans -= mod;
        }
    }
    printf("%d\n", ans);
    return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。http://blog.csdn.net/skywalkert

BZOJ 1974 [Sdoi2010] auction 代码拍卖会

DP+神奇的思路
  • SenyeLicone
  • SenyeLicone
  • 2017年03月01日 09:41
  • 156

[DP] BZOJ 1974 [Sdoi2010]auction 代码拍卖会 & 51Nod 1261 上升数

tls的题解 关键在于 对于一个上升数 比如 1123445 我们习惯性的把他纵向切割 1 1 2 3 4 4 5 但是只要我们转变一下 横向切割 变成 1111111+11111+1111+...
  • u014609452
  • u014609452
  • 2017年02月24日 01:22
  • 250

[转]Auction算法介绍

注:阅读资料,无链接,感觉写得挺好的。 一、传统拍卖竞价策略 1、英式拍卖(English Auction) 英式拍卖又叫公开增价拍卖OAB(Open Ascending Bid...
  • l18930738887
  • l18930738887
  • 2016年11月23日 11:38
  • 1906

Angular4搭建在线可竞拍网站

安装依赖包–save-dev 是你开发时候依赖的东西,–save 是你发布之后还依赖的东西。npm install jquery --save npm install bootstrap --save...
  • qq_33936481
  • qq_33936481
  • 2017年07月04日 14:10
  • 1262

2016-08-20-java-多线程的一个题目:用线程模拟竞拍过程

题目是这样的:用线程模拟竞拍过程 创建4条线程,代表4个人,设置线程名称分别为:(“匿名A”,“匿名B”,“匿名C”,“匿名D”)。 4个人一共可以竞拍8次,每次竞拍出的价为1-100(包含1和1...
  • guofengs
  • guofengs
  • 2016年08月20日 20:22
  • 1467

bzoj1974&jzoj1523 [Sdoi2010]auction 代码拍卖会

题意:当一个数的每一位都比前一位大时,我们把这种数叫做上升数。现在给你n和k,让你求n以内有多少个上升数能整除,n...
  • qq_35866453
  • qq_35866453
  • 2017年02月18日 14:05
  • 103

bzoj1974 [Sdoi2010]代码拍卖会 循环+背包

一般这种计数题就两个套路:找到倍数然后删除不合法的   找到合法的然后删除不是倍数的 如果先找倍数,那不合法的数位置和倍数没有直接关系 这个题是要先找合法的 然后删除不是倍数的 首先这个合法的数...
  • haobang866
  • haobang866
  • 2017年12月13日 17:24
  • 42

bzoj 1053: [HAOI2007]反素数ant && 51nod-1060:最复杂的数(反素数与因数个数计算)

问题概述:把一个数的约数个数定义为该数的复杂程度,给出一个n,求1-n中复杂程度最高的那个数。 例如:12的约数为:1 2 3 4 6 12,共6个数,所以12的复杂程度是6。如果有多个数复杂度相等,...
  • Jaihk662
  • Jaihk662
  • 2016年12月08日 22:42
  • 278

51nod-1134最长上升子序列

1134 最长递增子序列 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 给出长度为N的数组,找出这个数组的最长递增子序列。(递增子...
  • qq_33951440
  • qq_33951440
  • 2016年09月06日 19:36
  • 121

51nod1006最长上升子序列(求路径)

这道题目以前完全用char写,现在在尝试用string去写,感觉还不错,思路如下: 我们用Ax表示序列A的连续前x项构成的子序列,即Ax= a1,a2,……ax, By= b1,b2,……by, 我...
  • zcmartin2014214283
  • zcmartin2014214283
  • 2016年05月02日 17:23
  • 400
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:BZOJ 1974 [Sdoi2010]auction 代码拍卖会 | 51nod 1261 上升数
举报原因:
原因补充:

(最多只允许输入30个字)