zoukankan      html  css  js  c++  java
  • codeforces E

     说的是给了n个立方体,立方体从1标号到n,每个立方体上有一个数字, 你有 k 个机会 使得其中 k个数位他们自己的阶乘,(自然使用可以少于k次机会,每个立方体最多被使用1次) ,那么求出你从这n个立方体重选出任意个立方体使得 他们的和为S

    n<25

    可以知道直接使用n去枚举自然受不了, 我们将n个数字分为两部分来算,前面n/2个数字 我们枚举他们使用j次可以得到的数,然后后面的n-n/2个数再次使用这个方法,直接在dfs枚举的时候进行判断S-s 在前一个钟是否出现过,出现过就加起来。 分块处理 

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <string.h>
     4 #include <map>
     5 #include<cstdio>
     6 using namespace std;
     7 typedef long long LL;
     8 map<LL,int>mp[30];
     9 LL A[30];
    10 LL dp[30];
    11 LL time[1000000];
    12 int n,K;
    13 LL S,ans;
    14 void dfs(int p, int k, LL s){
    15     if(p==n/2){
    16          mp[k][s]++;
    17     }else{
    18         dfs(p+1,k,s);
    19         if(s+A[p]<=S)dfs(p+1,k,s+A[p]);
    20         if(k+1<=K && A[p]<=18 &&  s+dp[A[p]] <=S ) dfs(p+1,k+1,s+dp[A[p]]);
    21     }
    22 }
    23 void dfs1(int p, int k, LL s){
    24     if(p==n){
    25          for(int i =0; i+k<=K; i++)
    26             if(mp[i].count(S-s)>0) ans+=mp[i][S-s];
    27     }else{
    28          dfs1(p+1,k,s);
    29          if(s+A[p]<=S) dfs1(p+1,k,s+A[p]);
    30          if(k+1<=K && A[p]<=18 && s+dp[A[p]]<=S) dfs1(p+1,k+1,s+dp[A[p]]);
    31     }
    32 }
    33 int main()
    34 {
    35 
    36 
    37    dp[0]=1;
    38    for(LL i=1; i<=18; i++) dp[i]=dp[i-1]*i;
    39    ans=0;
    40    scanf("%d%d%I64d",&n,&K,&S);
    41    for(int i=0; i<n; i++)
    42       scanf("%I64d",&A[i]);
    43    dfs(0,0,0);
    44    dfs1(n/2,0,0);
    45    printf("%I64d
    ",ans);
    46     return 0;
    47 }
  • 相关阅读:
    [bzoj1251]序列终结者
    Codeforces #Round 406(Div.2)
    [3.23校内训练赛]
    [APIO2009]
    [APIO2016]
    [bzoj1901]动态区间k大
    [9018/1904]火星商店
    [bzoj3673/3674可持久化并查集加强版]
    [bzoj1297][SCOI2009]迷路
    [bzoj1218][HNOI2003]激光炸弹
  • 原文地址:https://www.cnblogs.com/Opaser/p/4381974.html
Copyright © 2011-2022 走看看