zoukankan      html  css  js  c++  java
  • snnu1111(子序列求和)

    1111: 子序列求和

    Time Limit: 3 Sec  Memory Limit: 64 MB
    Submit: 10  Solved: 2
    [Submit][Status][Web Board] [Edit]

    Description

    给出n个数字,分别为1,2,3,……,n。从中选出t个数字,且这t个数字和为x的方案数为ft,x 。给出m。输出下面的值:
     
    数据满足n <= 20000,m <= min(10, n)。

    Input

    第一行输入T表示测试数据的行数。接下来T行,每行两个数字n, m。T <= 20。

    Output

    对于每组测试数据,输出一行。

    Sample Input

    1 4 2

    Sample Output

    64

    HINT

    Source

    用d[t][x]表示t个数字和为x的方案数,且这t个数字中的最大数字不超过n。
    核心思想 : 给d[t][x]中的每个数字减掉一,变成d[t][x-t],d[t][x]应该等于d[t][x-t].
    如果这t个数字中的最小数字为1的话,减去1,最小数字就变为0,相当于t-1个数字,d[t-1][x-t]
    ,然而这两种情况都未考虑,最大数字不超过n的情况,假设d[t][x-t]中最大数字为n,给这t个数字每个加上1,
    那么最大数字就为n+1,超过n,所以,要去掉n+1,这个最大数字,减掉这种情况,相当于减掉d[t-1][x-t].
    还有一个坑就是A+B-C,由于要取模,所以A+B可能小于C,(A+B-C+MOD)%MOD;
     (d%MOD+MOD)%MOD;
    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    using namespace std;
    #define maxn 21000
    #define LL long long
    #define MOD  1000000007
    int n,m;
    LL answer;
    LL d[15][maxn*15];
    LL f[15];
    void init()
    {
        memset(d,0,sizeof(d));
        for(int i=1;i<15;i++)
            f[i]=1;
    }
    LL pow(int a,int b)
    {
        LL ans=1;
        for(int i=1;i<=b;i++)
        {
            ans=(ans*a)%MOD;
        }
        return ans;
    }
    void solve()
    {
        for(int i=1;i<=n;i++)
            d[1][i]=1;
            f[1]=pow(2,n);
         // cout<<f[1]<<endl;
         for(int t=2;t<=m;t++)
         {
             for(int x=1;x<(t*n);x++)
            {
                d[t][x]=(d[t][x-t]+d[t-1][x-t]-d[t-1][x-(n+1)] + MOD)%MOD;
    
                f[t]=(f[t]*(d[t][x]+1))%MOD;
                //printf("%d %d %d
    ",t,x,d[t][x]);
            }
            //最小值要么为1,要么不为1,
            //当最小值为1时,最大值可能为n,需要减去d[t-1][x-(n+1)];
            //当最小值不为1,最大值也可能为n,需要减去d[t-1][x-(n+1)];
            //由于这两种情况互斥,所以最多只需要减1次
             //cout<<endl;
           //  while(f[t]<0)
              //cout<<f[t]<<endl;
         }
    
         answer=0;
         for(int t=1;t<=m;t++)
         {
           //  printf("f %d %d
    ",t,f[t]);
              answer=(answer+f[t])%MOD;
              answer=answer%MOD;
         }
        // while(answer<0)
         printf("%lld
    ",answer%MOD);
    }
    int main()
    {
       // cout<<(-5)%3<<endl;
        int t;
        scanf("%d",&t);
        while(t--)
        {
           init();
           scanf("%d%d",&n,&m);
           solve();
        }
        return 0;
    }
  • 相关阅读:
    ASP.NET Core应用程序容器化、持续集成与Kubernetes集群部署(一)(转载)
    Python黑帽编程1.1虚拟机安装和配置 Kali Linux 2016
    kali linux 2016.1 滚动更新源
    使用you-get下载视频网站视频或其他
    asp.net core开发环境准备
    Python黑客编程基础3网络数据监听和过滤
    debian(kali Linux) 安装net Core
    嗅探、中间人sql注入、反编译--例说桌面软件安全性问题
    Python黑客编程2 入门demo--zip暴力破解
    kali linux Python开发环境初始化
  • 原文地址:https://www.cnblogs.com/xianbin7/p/4678186.html
Copyright © 2011-2022 走看看