(记忆化+暴力)UVA - 12627 Erratic Expansion

题意:一个数列,一开始只有一个1,进行k次操作,每次操作都把数列中原本的数全都翻倍然后追加在数列的后面,形成了一个全新的数列,输出全新数列中l到r的和。



分析:以上的题意是经过转化后的题意,变的非常简单,而不在卡在二维的思维中出不来。

可以看到如果在后半段,就等于前半段对应位置的两倍,可以从最高2^k个数的维护,k不断-1,最终变成维护数列中第一个1,直接返回1即可,形成了一个完美的递归。

 1 ll dg(int u ,int d,int k) {
 2     if(u==1&&d==1)return 1;
 3     int t=k>>1;
 4     if(d>t)return 2*dg(u-t,d-t,t);
 5     else if(u<=t)return dg(u,d,t);
 6     else return dg(t,d,t)+2*dg(u-t,1,t);
 7 }
 8
 9
10 void solve() {
11     int t;
12     scanf("%d",&t);
13     int s=0;
14     while(t--) {
15         int n,u,d;
16         scanf("%d%d%d",&n,&u,&d);
17         int a=1<<n;
18         printf("Case %d: %lld\n",++s,dg(a+1-u,a+1-d,a));
19     }
20 }

但是这样肯定会超市,如果每次都进入第三个if,复杂度直接飙升2^n。

我们可以想到用记忆化的方法,但是2^30二维数组开不下,可以用map来存就行了。



代码:

 1 #include <set>
 2 #include <map>
 3 #include <list>
 4 #include <cmath>
 5 #include <queue>
 6 #include <vector>
 7 #include <bitset>
 8 #include <string>
 9 #include <cctype>
10 #include <cstdio>
11 #include <cstring>
12 #include <cstdlib>
13 #include <iostream>
14 #include <algorithm>
15
16 using namespace std;
17
18 typedef long long ll;
19 typedef unsigned long long ull;
20 #define inf (0x3f3f3f3f)
21 #define lnf (0x3f3f3f3f3f3f3f3f)
22 #define eps (1e-8)
23 int sgn(double a){return a < -eps ? -1 : a < eps ? 0 : 1;}
24
25 //--------------------------
26
27 const int maxn=1000010;
28 map<pair<int,int>,ll> m;
29
30 ll dg(int u ,int d,int k) {
31     if(u==1&&d==1)return 1;
32     int t=k>>1;
33     if(d>t){
34         pair<int,int> p(u-t,d-t);
35         if(!m[p])m[p]=dg(u-t,d-t,t);
36         return 2*m[p];
37     }
38     else if(u<=t){
39         pair<int,int> p(u,d);
40         if(!m[p])m[p]=dg(u,d,t);
41         return m[p];
42     }
43     else {
44         pair<int,int> p1(t,d);
45         pair<int,int> p2(u-t,1);
46         if(!m[p1])m[p1]=dg(t,d,t);
47         if(!m[p2])m[p2]=dg(u-t,1,t);
48         return m[p1]+2*m[p2];
49     }
50 }
51
52
53 void solve() {
54     int t;
55     scanf("%d",&t);
56     int s=0;
57     while(t--) {
58         int n,u,d;
59         scanf("%d%d%d",&n,&u,&d);
60         int a=1<<n;
61         printf("Case %d: %lld\n",++s,dg(a+1-u,a+1-d,a));
62     }
63 }
64
65
66
67
68 int main() {
69
70 #ifndef ONLINE_JUDGE
71     freopen("in.txt", "r", stdin);
72     freopen("out.txt", "w", stdout);
73 #endif
74     //iostream::sync_with_stdio(false);
75     solve();
76     return 0;
77 }
时间: 2024-10-10 14:18:39

(记忆化+暴力)UVA - 12627 Erratic Expansion的相关文章

uva 12627 - Erratic Expansion(递归求解)

递归的边界条件写的多了--没必要写呢么多的.. 不明白可共同探讨~ #include<cstdio> #include<iostream> #include<cmath> using namespace std; long long dp(int kk,int pos) { int n=kk;int temp=(int)pow(2,n); // printf("%d %d\n",kk,pos); if(kk==0&&pos==1) r

(白书训练计划)UVa 12627 Erratic Expansion(递归+找规律)

题目地址:UVa 12627 这题是先找规律,规律在于对于第k个小时的来说,总是可以分成右下角全是蓝色气球,右上角,左下角与左上角三个一模一样的k-1个小时的气球.这样的话,规律就很清晰了,然后用递归做比较方便... 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <ma

UVA - 12627 Erratic Expansion(奇怪的气球膨胀)(递归)

题意:问k小时后,第A~B行一共有多少个红气球. 分析:观察图可发现,k小时后,图中最下面cur行的红气球个数满足下式: (1)当cur <= POW[k - 1]时, dfs(k, cur) = dfs(k - 1, cur); (2)当cur > POW[k - 1]时, dfs(k - 1, cur) = 2 * dfs(k - 1, cur - POW[k - 1]) + tot[k - 1]; 其中,POW[k - 1]为2^(k  - 1),tot[k - 1]为k-1小时后图中的

Uva 12627 Erratic Expansion(递归)

这道题大体意思是利用一种递归规则生成不同的气球,问在某两行之间有多少个红气球. 我拿到这个题,一开始想的是递归求解,但在如何递归求解的思路上我的方法是错误的.在研读了例题上给出的提示后豁然开朗(顺便吐槽一下算法竞赛第二版在这这道题目上(P246)提示写的有问题,g(k,i)=2g(k-1,i-2^(k-1))+c(k-1)  ,他把c(k-1)写成了c(k)...我纠结这个纠结了好久) 根据题目提示,这道题可以用f(k,i)表示k小时后最上边i行的红气球总数 那么我们的答案就可以表示为f(k,b

UVA 12627 Erratic Expansion

#include<bits/stdc++.h> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int maxn=1000100; const int INF=1<<29; ll k,a,b; ll s[maxn]; ll f(ll i,ll k) { if(i==0) r

UVA - 12627 Erratic Expansion 奇怪的气球膨胀 (分治)

紫书例题p245 Piotr found a magical box in heaven. Its magic power is that if you place any red balloon inside it then, after one hour, it will multiply to form 3 red and 1 blue colored balloons. Then in the next hour, each of the red balloons will multip

状压DP+记忆化搜索 UVA 1252 Twenty Questions

题目传送门 1 /* 2 题意:给出一系列的01字符串,问最少要问几个问题(列)能把它们区分出来 3 状态DP+记忆化搜索:dp[s1][s2]表示问题集合为s1.答案对错集合为s2时,还要问几次才能区分出来 4 若和答案(自己拟定)相差小于等于1时,证说明已经能区分了,回溯.否则还要加问题再询问 5 */ 6 /************************************************ 7 * Author :Running_Time 8 * Created Time :

记忆化搜索 UVA 103

#include<stdio.h> #include<algorithm> #include<string.h> #include<vector> #include<iostream> using namespace std; struct node { int wei[40]; }ed[40]; int n,m; int dp[40]; vector<int> map[40]; int path[40]; int dfs(int u

AC自动机+全概率+记忆化DP UVA 11468 Substring

题目传送门 题意:训练之南P217 分析:没有模板串也就是在自动机上走L步,不走到val[u] == v的节点的概率 PS:边读边insert WA了,有毒啊! #include <bits/stdc++.h> using namespace std; const int K = 20 + 5; const int L = 100 + 5; const int NODE = K * K; const int SIZE = 66; int idx[256], n; struct AC { int