zoukankan      html  css  js  c++  java
  • lightoj 1125【背包·从n个选m个】

    题意:
    给你 n 个背包,然后给你两个数,D,M,问你从n个里面挑M个出来,有多少种方法能够整除D;


    思路:

    试想我先不挑M个出来的话,仅仅是构造一个D的倍数,其实就是构造一个数的话,
    其实就是个递推,然后方案的叠加

    挑M个,D的倍数。
    能对M个状压;
    但是对于D的倍数呢?
    其实就是取膜就好了,比如5的倍数,
    那么dp[个数][j]+=dp[个数-1][j-X];(个数都是状压了)

    但是现在是200个里面挑10个啊。。。
    不行的话就再加一维。
    所以还是要从前 i 个物品推过来。。。
    所以现在可以搞成dp[i][j][k]表示前i个物品选j个%D=k时的方案数;= =

    每次逆推可以把第一维去掉,时间复杂度也OK;


    总的来说就是:能状压么?不能解决这个事情就再开一维,一维不行上二维,二维不行三维先上了再说;(PS:n个里面选m个真是玄学。。第二遍做。。。还是碰壁GG。


    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    typedef pair<int,int>PII;
    const double eps=1e-5;
    const double pi=acos(-1.0);
    const int INF=0x3f3f3f3f;
    const int N=1e2+10;
    
    int a[N*2];
    LL dp[12][25];
    
    int main()
    {
        int cas=1;
        int n,w,q,d,m;
        int t,x,sum;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d",&n,&q);
                for(int i=1;i<=n;i++)
                    scanf("%d",&a[i]);
    
            printf("Case %d:
    ",cas++);
    
            for(int k=1;k<=q;k++)
            {
                scanf("%d%d",&d,&m);
                memset(dp,0,sizeof(dp));
                dp[0][0]=1LL;
                for(int i=1;i<=n;i++)
                {
                    int temp=a[i]%d;
                    for(int j=m;j>=1;j--)
                        for(int x=0;x<d;x++)
                            dp[j][x]+=dp[j-1][(x+d-temp)%d];
                }
                printf("%lld
    ",dp[m][0]);
            }
        }
        return 0;
    }
    


  • 相关阅读:
    【hdu4035】Maze
    【bzoj2707】走迷宫
    【CF123E】Maze
    【CF113D】Museum
    【recording】gdoi2018
    最近公共祖先(LCA)(题目)
    回转寿司
    counting
    B
    A
  • 原文地址:https://www.cnblogs.com/keyboarder-zsq/p/6777490.html
Copyright © 2011-2022 走看看