SRM 601 DIV1

A

  枚举x , 然后对于确定的x , 最后总的apple数对应了唯一的orange数,因此问题转化为求apple的取值范围;

  apple的取值范围: max为每个bag取最多的apple , min为每个bag取最小的apple , 容易证明[min,max]是连续的.

  

 1 using namespace std;
 2 
 3 class WinterAndPresents {
 4 public:
 5     long long getNumber(vector <int>, vector <int>);
 6 };
 7 struct node {
 8     int a,o;
 9 };vector<node> f;
10 bool cmp(node x,node y) {
11     if (x.a==y.a) return x.o<y.o;
12     return x.a<y.a;
13 }
14 long long WinterAndPresents::getNumber(vector <int> apple, vector <int> orange) {
15     long long ans = 0;
16     int x = -1,n = apple.size();
17     for (int i=0 ; i<n ; i++ ) {
18         if (x==-1 || x>apple[i]+orange[i]) x=apple[i]+orange[i];
19         f.push_back((node){apple[i],orange[i]});
20     }
21     for (int i=1 ; i<=x ; i++ ) {
22         long long big = 0 , sml = 0;
23         for (int j=0 ; j<n ; j++ ) {
24             if (f[j].a>=i) big += i;
25             else big += f[j].a;
26             
27             if (f[j].o>=i) sml += 0;
28             else sml += i-f[j].o;
29         }
30         ans += big-sml+1;
31     }
32     return ans;
33 }
View Code

 

B

  关键在于优化dp状态.

  朴素的dp是: dp[i][mask1][mask2]  在考虑第i个数时 集合1的状态为mask1 , 集合2的状态为mask2.

  为了优化掉一维,应该考虑把状态设计成 dp[i][mask1^mask2] , 然后为了识别大小再用1维记录最高非0位属于哪个集合,

  再换个角度来看,可以枚举最后最高非0位在位置p , 然后用dp[i][mask1^mask2][0/1]表示:

    选择了i个 ; 集合1,2的异或值异或为mask1^mask2 ; mask1在p位置是0/1

  就把原来的 O(maxn*mask1*mask2) 复杂度优化为O(maxn*mask1*2*log(maxn))

  最后,在实现的时候可以把 (mask1^mask2) 右移p位 , 因为最高非零位之后的都无关紧要, 此时的状态数变更小了,用dfs实现可以更快.

 1 #include <vector>
 2 #include <list>
 3 #include <map>
 4 #include <set>
 5 #include <deque>
 6 #include <stack>
 7 #include <bitset>
 8 #include <algorithm>
 9 #include <functional>
10 #include <numeric>
11 #include <utility>
12 #include <sstream>
13 #include <iostream>
14 #include <iomanip>
15 #include <cstdio>
16 #include <cmath>
17 #include <cstdlib>
18 #include <ctime>
19 #include <cstring>
20 using namespace std;
21 #define mod 1000000007
22 class WinterAndSnowmen {
23 public:
24     int getNumber(int, int);
25 };
26 int dp[2001][1<<11][2],p,n,m;
27 int dfs(int t,int sum,int b) {
28     //printf("t:%d sum:%d b:%d\n",t,sum,b);
29     if (t==0) {
30     //    printf("p:%d sum:%d b:%d\n",p,sum,b);
31         if ( sum==1 && b==0 ) return 1;
32         else return 0;
33     }
34     if (dp[t][sum][b]!=-1) return dp[t][sum][b];
35     else {
36         long long res = 0;
37         if (t<=n) {
38             res += dfs( t-1 , sum^(t>>p) , b^((t>>p)&1) );
39         }
40         if (t<=m) {
41             res += dfs(t-1 , sum^(t>>p) , b );
42         }
43         res += dfs( t-1 , sum , b );
44         res %= mod;
45         return dp[t][sum][b]=(int)res;
46     }
47 }
48 int WinterAndSnowmen::getNumber(int N, int M) {
49     int res = 0;
50     n = N , m = M;
51     for (int i=0 ; i<11 ; i++ ) {
52         memset(dp,-1,sizeof(dp));
53         p = i;
54         res += dfs(max(N,M),0,0);
55         res %= mod;
56     //    printf("i:%d add:%d\n",i,tmp);
57     }
58     return res;
59 }
60 
61 
62 //Powered by [KawigiEdit] 2.0!
View Code

 

C

  又是个需要状态优化的dp.

  朴素的状态设计是: f(t , r0 , g0 , b0 , r1 , g1 , b1) , 表示第t天 , 第一个shop的销售情况和第二个shop的销售情况;

  但是考虑到两个shop同时营业时 , 销售情况必须一致 , 当碰到有同时营业的情况时 , 可以直接跳到下一个结束点:

    于是新的状态表示为 f(t,r0,g0,b0) ;

  然后再通过各种判断,来知道如何转移;

  进一步优化是去掉b0的记录, 因为每天必须售出一个ball ,  知道当前天t,开始天first,已经其它销售情况就能计算出b0.

  最后的状态表示为f(t,r0,g0).

  

 1 using namespace std;
 2 #define maxn 510
 3 #define mod 1000000007
 4 class WinterAndShopping {
 5 public:
 6     int getNumber(vector <int>, vector <int>, vector <int>, vector <int>);
 7 };
 8 
 9 struct node{
10     int f,r,g,b;
11     int end() {
12         return f+r+g+b;
13     }
14 };vector<node> s[maxn];
15 int dp[maxn][101][101],c[maxn][maxn];
16 
17 void pretreat(vector<int> f, vector<int> r, vector<int> g, vector<int> b) {
18     for (int i=0 ; i<(int)f.size() ; i++ ) {
19         for (int j=f[i] ; j<f[i]+r[i]+g[i]+b[i] ; j++ ) {
20             s[j].push_back((node){f[i],r[i],g[i],b[i]});
21         }
22     }
23     for (int i=0 ; i<maxn ; i++ ) if (s[i].size()==2) {
24         if (s[i][0].f>s[i][1].f) swap(s[i][0],s[i][1]);
25     }
26     for (int i=0 ; i<maxn ; i++ ) {
27         c[i][0] = 1;
28         for (int j=1 ; j<=i ; j++ )
29             c[i][j] = (c[i-1][j-1] + c[i-1][j]) % mod;
30     }
31 }
32 
33 long long getfct(int r,int g,int b) {
34     long long res = (long long)c[r+g+b][r] * (long long )c[g+b][g] % mod;
35 //    printf("r:%d g:%d b:%d res:%lld\n",r,g,b,res);
36     return res;
37 }
38 
39 long long dfs(int t,int r,int g) {
40     if (t==501) {
41         if (r==0 && g==0) return 1;
42         else return 0;
43     }
44     if (dp[t][r][g]!=-1) return (long long)dp[t][r][g];
45     else {
46         long long res = 0;
47         if (s[t].size()==0) res = dfs(t+1,0,0);
48         else if (s[t].size()==1) {
49             if (t+1 == s[t][0].end()) res = dfs(t+1,0,0);
50             else {
51                 if (r+1<=s[t][0].r) res += dfs(t+1,r+1,g);
52                 if (g+1<=s[t][0].g) res += dfs(t+1,r,g+1);
53                 if (t-s[t][0].f-r-g+1<=s[t][0].b) res += dfs(t+1,r,g);
54             }
55             res %= mod;
56         }
57         else if (s[t].size()==2) {
58             node s0 = s[t][0] , s1 = s[t][1];
59             int b = (t-s0.f-(r+g));
60             if (s0.end() == s1.end()) {
61                 if (s0.r-r==s1.r && s0.g-g==s1.g && s0.b-b==s1.b) {
62                     res = getfct(s1.r,s1.g,s1.b) * dfs(s1.end(),0,0) % mod;
63                 }
64             } else if (s0.end() < s1.end()) {
65                 if (s0.r-r<=s1.r && s0.g-g<=s1.g && s0.b-b<=s1.b) {
66                     res = getfct(s0.r-r,s0.g-g,s0.b-b) * dfs(s0.end(),s0.r-r,s0.g-g) % mod;
67                 }
68             } else if (s0.end() > s1.end()) {
69                 if (s1.r<=s0.r-r && s1.g<=s0.g-g && s1.b<=s0.b-b) {
70                     res = getfct(s1.r,s1.g,s1.b) * dfs(s1.end(),r+s1.r,g+s1.g) % mod;
71                 }
72             }
73         }
74         dp[t][r][g] = (int)res;
75         return res;
76     }
77 }
78 
79 int WinterAndShopping::getNumber(vector <int> f, vector <int> r, vector <int> g, vector <int> b) {
80     pretreat(f,r,g,b);
81     memset(dp,-1,sizeof(dp));
82     long long ans = dfs(0,0,0);
83     return (int)ans;
84 }
View Code

 

转载于:https://www.cnblogs.com/eggeek/p/3537565.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值