zoukankan      html  css  js  c++  java
  • [SDOI2010]代码拍卖会

    题目描述

    随着iPig在P++语言上的造诣日益提升,他形成了自己一套完整的代码库。猪王国想参加POI的童鞋们都争先恐后问iPig索要代码库。iPig不想把代码库给所有想要的小猪,只想给其中的一部分既关系好又肯出钱的小猪,于是他决定举行了一个超大型拍卖会。

    在拍卖会上,所有的N头小猪将会按照和iPig的好感度从低到高,从左到右地在iPig面前站成一排。每个小猪身上都有9猪币(与人民币汇率不 明),从最左边开始,每个小猪依次举起一块牌子,上面写上想付出的买代码库的猪币数量(1到9之间的一个整数)。大家都知道,如果自己付的钱比左边的猪 少,肯定得不到梦寐以求的代码库,因此从第二只起,每只猪出的钱都大于等于左边猪出的价钱。最终出的钱最多的小猪(们)会得到iPig的代码库真传,向着 保送PKU(Pig Kingdom University)的梦想前进。

    iPig对自己想到的这个点子感到十分满意,在去现场的路上,iPig就在想象拍卖会上会出现的场景,例如一共会出现多少种出价情况之类的问题,但 这些问题都太简单了,iPig早已不敢兴趣了,他想要去研究更加困难的问题。iPig发现如果他从台上往下看,所有小猪举的牌子从左到右将会正好构成一个 N位的整数,他现在想要挑战的问题是所有可能构成的整数中能正好被P整除的有多少个。由于答案过大,他只想要知道答案mod 999911659就行了。

    输入输出格式

    输入格式:

    输入文件auction.in有且仅有一行:两个数N(1≤N≤10^18)、P(1≤P≤500),用一个空格分开。

    输出格式:

    输入文件auction.out有且仅有一行:一个数,表示答案除以999911659的余数。

    输入输出样例

    输入样例#1:
    2 3
    输出样例#1:
    15

    说明

    样例解释

    方案可以是:12 15 18 24 27 33 36 39 45 48 57 66 69 78 99,共15种。

    数据规模

    给定N,P,有一个数A是N位数,并且A的每一位不减(如11234)并且不超过9,求能被P整除的数有多少个。

    分 析:首先我们注意到N非常大,O(N)绝对不能接受,但是P只有500,而且A这个数有非常奇妙的性质:由于A的每一位不减,所以可以将A拆成 0,1,11,111,1111,11111……中取九个的和(如11234=11111+111+11+1+0+0+0+0+0),这样一来,由于 11…111 mod P会出现循环,就可以将N从复杂度中消去,记Cnt[i]表示0,1,11……中mod P 为i的个数(0 <= I < P),题目就变成了从Cnt[i]中取九个使下标之和被P整除;
    于是可以容易的想到动态规划,F[i][j][k]表示做到Cnt[i],当前取了k个,k个的和mod P为j,转移方程就是
    F[i + 1][(j + l * i) % P][k + l] = (F[i][j][k] * Calc(l, Cnt[i]) + F[i + 1][(j + l * i) % P][k + l]) % mod;(枚举l)
    其中Calc(l, Cnt[i])表示Cnt[i]中无差别的取出l个(可以重复)的方案数,根据排列组合的定理可知Calc(A, B) = C(A+B-1,A) 
    复杂度:O(P*P*9*9)
    记得最后的数还要加上111...11(n个1).因为在DP的时候这个数是可以有前导0的。
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 typedef long long lol;
     7 lol Mod=999911659,ans;
     8 lol n,p,cnt[501],beg,len,pos[501],A[10],c[501][11],f[501][501][11],a;
     9 int main()
    10 {lol i,j,k,l;
    11   cin>>n>>p;
    12   lol sum=0;
    13   if (n<=p) 
    14     {
    15       for (i=1;i<=n;i++)
    16     {
    17       sum=sum*10+1;
    18       sum%=p;
    19       cnt[sum]++;
    20     }
    21       a=sum;
    22     }
    23      else 
    24      { 
    25        for (i=1;i<=p+1;i++)
    26      {
    27        sum=sum*10+1;
    28        sum%=p;
    29        if (cnt[sum])
    30          {
    31            beg=pos[sum];
    32            len=i-pos[sum];
    33            break;
    34          }
    35        cnt[sum]++;
    36        pos[sum]=i;
    37      }
    38        for (i=0;i<p;i++)
    39      if (cnt[i]&&pos[i]>=beg)
    40        {
    41          cnt[i]=(n-beg+1)/len;
    42          if (pos[i]-beg+1<=(n-beg+1)%len) cnt[i]++;
    43          if ((pos[i]-beg+1)%len==(n-beg+1)%len) a=i;
    44        }
    45      }
    46   A[1]=1;
    47   for (i=2;i<=8;i++)
    48     A[i]=(Mod-Mod/i)*A[Mod%i]%Mod;
    49    for (i=0;i<p;i++)
    50     {
    51       c[i][0]=1;
    52       if (cnt[i])
    53       for (j=1;j<=8;j++)
    54     {
    55       c[i][j]=(cnt[i]*c[i][j-1]%Mod)*A[j]%Mod;
    56         cnt[i]++;cnt[i]%=Mod;
    57     }
    58     }
    59    f[0][a][0]=1;
    60   for (i=0;i<p;i++)
    61     {
    62       for (j=0;j<p;j++)
    63     {
    64       for (k=0;k<9;k++)
    65         {
    66           for (l=0;l<=k;l++)
    67         {
    68           f[i+1][j][k]+=f[i][(j-(l*i%p)+p)%p][k-l]*c[i][l]%Mod;
    69           f[i+1][j][k]%=Mod;
    70           //cout<<i+1<<' '<<j<<' '<<k<<' '<<l<<' '<<f[i+1][j][k]<<endl;
    71         }
    72         }
    73     }
    74     }
    75   for (i=0;i<=8;i++)
    76     ans+=f[p][0][i],ans%=Mod;
    77   cout<<ans;
    78 }
  • 相关阅读:
    asp .net 页面回车触发button 按钮事件
    Asp.netPost&Get转
    2012.8.16近期总结,1模态窗口回传重新被弹出2,清空缓存 3,
    面试感言
    2012.6.27近期总结,1.sql字符串转换(cast,CONVERT )调用wcf服务,关闭模态窗口刷新付页面
    self
    空指针
    枚举和结构体
    typedef
    指针
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7701143.html
Copyright © 2011-2022 走看看