• [容斥原理][dp]JZOJ P3056 数字


    【问题描述】


        一个数字被称为好数字当他满足下列条件:


    1. 它有2*n个数位,n是正整数(允许有前导0)   


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


        3. 它前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。

    题解

    • 显然我们可以问题为:
    • 前n位之和与后n位之和相等的方案数+奇数位之和与偶数位之和相等的方案数-前n位之和与后n位之和相等且奇数位之和与偶数位之和相等的方案数

    • 根据容斥原理可以将最后一个转换为:
    • 前n位奇数位之和=后n位偶数位之和 且 前n位偶数位之和=后n位奇数位之和

    • 那么前两个都很容易求,跑一遍dp,f[i][j]表示i个数和为j的可能的方案数
    • 那么i个数可以为n个奇数,也可以为n个偶数
    • 那么前两个的和就是∑(i=1,i<=n*9)2*f[n][i]*f[n][i] (ans)
    • 定义两个数l1=(n+1)/2,l2=n/2
    • l1为前n个数的奇数个数和后n个数的偶数个数
    • l2为前n个数的偶数个数和后n个数的奇数个数
    • 知道这个后方案数自然很容易求
    • ans1=(ans1+f[l1][i]%mo*f[l1][i])%mo; ans2=(ans2+f[l2][i]%mo*f[l2][i])%mo;
    • 答案为ans-ans1*ans2
    • 注意要取膜

    代码

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 using namespace std;
     5 const int mo=999983;
     6 int n,len,a[15];
     7 long long ans1,ans2,sum,f[1005][1005*9];
     8 char s[15];
     9 int main()
    10 {
    11     scanf("%d",&n);
    12     scanf("%s",s+1);
    13     len=strlen(s+1);
    14     for (int i=1;i<=len;i++) a[i]=s[i]-'0';
    15     f[0][0]=1;
    16     for (int i=1;i<=n;i++)
    17         for (int j=0;j<=i*9;j++)
    18             for (int k=1;k<=len;k++)
    19                 if (j-a[k]>=0)
    20                     f[i][j]=(f[i][j]+f[i-1][j-a[k]])%mo;
    21     for (int i=0;i<=n*9;i++) sum=(sum+2*f[n][i]%mo*f[n][i])%mo;
    22     int l1=(n+1)/2,l2=n/2;
    23     for (int i=0;i<=l1*9;i++) ans1=(ans1+f[l1][i]%mo*f[l1][i])%mo;
    24     for (int i=0;i<=l2*9;i++) ans2=(ans2+f[l2][i]%mo*f[l2][i])%mo;
    25     printf("%lld",(sum-ans1*ans2%mo+mo)%mo);
    26 }
  • 相关阅读:
    1062 Talent and Virtue (25 分)
    1083 List Grades (25 分)
    1149 Dangerous Goods Packaging (25 分)
    1121 Damn Single (25 分)
    1120 Friend Numbers (20 分)
    1084 Broken Keyboard (20 分)
    1092 To Buy or Not to Buy (20 分)
    数组与链表
    二叉树
    时间复杂度与空间复杂度
  • 原文地址:https://www.cnblogs.com/Comfortable/p/8562344.html
Copyright © 2020-2023  润新知