zoukankan      html  css  js  c++  java
  • 数字

    Description

    【问题描述】

    一个数字被称为好数字当他满足下列条件:
    
    1. 它有2*n个数位,n是正整数(允许有前导0)

    2. 构成它的每个数字都在给定的数字集合S中。

      1. 它前n位之和与后n位之和相等或者它奇数位之和与偶数位之和相等

      例如对于n=2,S={1,2},合法的好数字有1111,1122,1212,1221,2112,2121,2211,2222这样8种。

    已知n,求合法的好数字的个数mod 999983。

    Input

    第一行一个数n。
    
    
    接下来一个长度不超过10的字符串,表示给定的数字集合。
    

    Output

    一行一个数字表示合法的好数字的个数mod 999983。
    

    Sample Input
    2
    0987654321

    Sample Output
    1240

    Data Constraint

    Hint
    对于20%的数据,n≤7。
    对于100%的.据,n≤1000,|S|≤10。
    .
    .
    .
    .
    .
    .

    分析

    首先我们设递推数组fi,j表示用i个数字加起来能达到j的方案数
    预处理:f0,0=1
    然后我们可以得出递推式为:
    fi,j=∑fi-1,j-a[k](k=1~n并j-a[k]>=0)% 999983
    (提示,j最大值为i*ak中最大值,但作者偷懒直接用9。反正都一样啦,至于为什么自己思考一下)
    然后,我们可以发现,由于是2n的序列,所以前n位与后n位相等和奇数位与偶数位相等的方案数是一样的,所以乘2即可
    方案总数为2*∑fn,i*fn,i(i=0~n*9)

    我们可以很轻易地发现前n位与后n位相等的时候,有一些情况会和奇数位与偶数位相等的方案重叠
    所以我们要减掉一些
    减掉什么呢?
    我们发现,上面的情况就相当于前n位的奇偶数位相等和后n位的奇偶数位相等
    所以式子是:
    (接下来l1表示n中的奇数个数,l2表示n中的偶数个数)
    (∑fl1,i(i=0~l1*9)∑fl2,i(i=0~l2*9))(∑fl1,i(i=0~l1*9)*∑fl2,i(i=0~l2*9))
    然后乘法分配律得
    ∑fl1,i(i=0~l1*9)²∑fl2,i(i=0~l2*9)²
    然后之前的值减去这个时,可能为负数(因为求余,并不是算法特判),所以要加999983后模999983。
    .
    .
    .
    .
    .
    .

    程序:
    const
    mo=999983;
    var
    n,i,j,k,l,l1,l2:longint;
    s:string;
    a:array[0..10]of longint;
    ans1,ans2,ans:int64;
    f:array[0..1001,0..9001]of int64;
    
    begin
        readln(n);
        readln(s);
        l:=length(s);
        for i:=1 to l do
        a[i]:=ord(s[i])-ord('0');
        f[0,0]:=1;
        for i:=1 to n do
        for j:=0 to i*9 do
        for k:=1 to l do
        if (j-a[k]>=0) then f[i,j]:=(f[i,j]+f[i-1,j-a[k]]) mod mo;
        for i:=0 to n*9 do
        ans:=(ans+2*f[n,i]*f[n,i]) mod mo;
        l1:=(n+1) div 2;
        l2:=n div 2;
        for i:=0 to l1*9 do
        ans1:=(ans1+f[l1,i]*f[l1,i] mod mo) mod mo;
        for i:=0 to l2*9 do
        ans2:=(ans2+f[l2,i]*f[l2,i] mod mo) mod mo;
        ans:=(ans-ans1*ans2 mod mo +mo) mod mo;
        write(ans);
    end.
    
  • 相关阅读:
    Linux-文件目录管理
    20. 有效的括号
    242. 有效的字母异位词
    387. 字符串中的第一个唯一字符
    136. 只出现一次的数字
    14. 最长公共前缀
    268. 丢失的数字
    169. 多数元素
    26. 删除有序数组中的重复项
    283. 移动零
  • 原文地址:https://www.cnblogs.com/YYC-0304/p/9499960.html
Copyright © 2011-2022 走看看