2015-02-07 21:34:53
总结:这场开场有点慢了... 还好前三题都是可做题。搞了三题+1hack,rank30。
A:因为是幂的比较,所以考虑到两边取log,然后直接比较即可。但是卡了下精度,要先看是否相等(fabs()< 1e-10),然后再判大小。
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <vector> 6 #include <map> 7 #include <set> 8 #include <stack> 9 #include <queue> 10 #include <string> 11 #include <iostream> 12 #include <algorithm> 13 using namespace std; 14 15 #define MEM(a,b) memset(a,b,sizeof(a)) 16 #define REP(i,n) for(int i=0;i<(n);++i) 17 #define REV(i,n) for(int i=(n-1);i>=0;--i) 18 #define FOR(i,a,b) for(int i=(a);i<=(b);++i) 19 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i) 20 #define getmid(l,r) ((l) + ((r) - (l)) / 2) 21 #define MP(a,b) make_pair(a,b) 22 23 typedef long long ll; 24 typedef pair<int,int> pii; 25 const int INF = (1 << 30) - 1; 26 27 double a,b,c,d; 28 double A,B; 29 30 int main(){ 31 while(scanf("%lf%lf%lf%lf",&a,&b,&c,&d) != EOF){ 32 A = 1.0 * b * log(1.0 * a); 33 B = 1.0 * d * log(1.0 * c); 34 if(fabs(A - B) < 1e-10) printf("=\n"); 35 else if(A > B) printf(">\n"); 36 else printf("<\n"); 37 } 38 return 0; 39 }
B:因为k很大,而且有模数,所以是比较明显的快速幂题。考虑到是不断地取最大的两个数,然后相加... 于是我们就有这样的转移方程,最大的两个数赋为v[1],v[2],转移方程:
× = 需要注意的一点是防止超int,全部开成 long long
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <vector> 6 #include <map> 7 #include <set> 8 #include <stack> 9 #include <queue> 10 #include <string> 11 #include <iostream> 12 #include <algorithm> 13 using namespace std; 14 15 #define MEM(a,b) memset(a,b,sizeof(a)) 16 #define REP(i,n) for(int i=0;i<(n);++i) 17 #define REV(i,n) for(int i=(n-1);i>=0;--i) 18 #define FOR(i,a,b) for(int i=(a);i<=(b);++i) 19 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i) 20 #define getmid(l,r) ((l) + ((r) - (l)) / 2) 21 #define MP(a,b) make_pair(a,b) 22 23 typedef long long ll; 24 typedef pair<int,int> pii; 25 const int INF = (1 << 30) - 1; 26 const ll mod = 10000007; 27 28 ll n,k,val[100010]; 29 30 struct Mx{ 31 ll a[3][3]; 32 void clear(){ memset(a,0,sizeof(a));} 33 void stand(){ memset(a,0,sizeof(a)); for(int i = 0; i < 3; ++i) a[i][i] = 1;} 34 Mx operator * (Mx b){ 35 Mx c; c.clear(); 36 for(int i = 0; i < 3; ++i){ 37 for(int j = 0; j < 3; ++j){ 38 for(int k = 0; k < 3; ++k){ 39 c.a[i][j] = (c.a[i][j] + a[i][k] * b.a[k][j] % mod) % mod; 40 } 41 } 42 } 43 return c; 44 } 45 }; 46 47 Mx Q_pow(ll num){ 48 Mx t; t.clear(); 49 Mx res; res.stand(); 50 t.a[0][1] = 1; 51 t.a[1][0] = t.a[1][1] = 1; 52 t.a[2][0] = t.a[2][1] = t.a[2][2] = 1; 53 while(num){ 54 if(num & 1) res = res * t; 55 t = t * t; 56 num >>= 1; 57 } 58 return res; 59 } 60 61 int main(){ 62 while(scanf("%I64d%I64d",&n,&k) != EOF){ 63 REP(i,n) scanf("%I64d",&val[i]); 64 ll sum = 0; 65 sort(val,val + n); 66 for(int i = 0; i < n - 2; ++i) sum = (sum + val[i]) % mod; 67 Mx ans; 68 ans.clear(); 69 ans.a[0][0] = val[n - 2]; 70 ans.a[1][0] = val[n - 1]; 71 ans.a[2][0] = val[n - 1] + val[n - 2]; 72 ans = Q_pow(k) * ans; 73 printf("%I64d\n",(ans.a[2][0] + sum) % mod); 74 } 75 return 0; 76 }
C:一开始想暴力搞... 后来发现涉及区间询问,果断上了线段树
这题有两个模型:小白书的贪心例题(区间相关问题),线段树优化。
首先按照询问区间的右端点进行排序,然后逐个处理询问,逐个扫描序列,保存下每个数的最右位置(其实从左到右扫的话就是不断更新各个数的位置)
对于每个询问,比如是[4,10],区间长度是7,那么我们只要知道1~7这些数的最右位置是否都在[4,10]内就可以了,再进一步只要知道1~7的最小位置是否是4即可。(思考)
直接暴力必定超时,只要加一颗线段树来维护区间最小值即可。(赛后数据改大了... QAQ)
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <vector> 6 #include <map> 7 #include <set> 8 #include <stack> 9 #include <queue> 10 #include <string> 11 #include <iostream> 12 #include <algorithm> 13 using namespace std; 14 15 #define MEM(a,b) memset(a,b,sizeof(a)) 16 #define REP(i,n) for(int i=0;i<(n);++i) 17 #define REV(i,n) for(int i=(n-1);i>=0;--i) 18 #define FOR(i,a,b) for(int i=(a);i<=(b);++i) 19 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i) 20 #define getmid(l,r) ((l) + ((r) - (l)) / 2) 21 #define MP(a,b) make_pair(a,b) 22 23 typedef long long ll; 24 typedef pair<int,int> pii; 25 const int INF = (1 << 30) - 1; 26 const int MAXN = 1000010; 27 28 int n,m; 29 int val[MAXN]; 30 int ans[MAXN]; 31 int tmin[MAXN]; 32 int L,R,A,C; 33 34 struct edge{ 35 int l,r,id; 36 }e[MAXN]; 37 38 inline int Read(){ 39 int x = 0,f = 1;char ch = getchar(); 40 while(ch < '0' || ch > '9'){if(ch == '-')f = -1;ch = getchar();} 41 while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();} 42 return x * f; 43 } 44 45 bool cmp(edge a,edge b){ 46 if(a.r == b.r) 47 return a.l < b.l; 48 return a.r < b.r; 49 } 50 51 struct SMT{ 52 int tmin[MAXN << 2]; 53 void clear(){ 54 memset(tmin,0,sizeof(tmin)); 55 } 56 void Update(int p,int l,int r){ 57 if(l == r){ 58 tmin[p] = C; 59 return; 60 } 61 int mid = getmid(l,r); 62 if(val[C] <= mid) Update(p << 1,l,mid); 63 else Update(p << 1|1,mid + 1,r); 64 tmin[p] = min(tmin[p << 1],tmin[p << 1|1]); 65 } 66 int Query(int p,int l,int r){ 67 if(1 <= l && r <= R) 68 return tmin[p]; 69 int mid = getmid(l,r); 70 int res = INF; 71 if(1 <= mid) res = min(res,Query(p << 1,l,mid)); 72 if(R > mid) res = min(res,Query(p << 1|1,mid + 1,r)); 73 return res; 74 } 75 }smt; 76 77 int main(){ 78 while(scanf("%d%d",&n,&m) != EOF){ 79 smt.clear(); 80 FOR(i,1,n) val[i] = Read(); 81 FOR(i,1,m){ 82 e[i].l = Read(); 83 e[i].r = Read(); 84 e[i].id = i; 85 } 86 sort(e + 1,e + m + 1,cmp); 87 C = 1; 88 FOR(i,1,m){ 89 for(; C <= e[i].r; ++C) 90 smt.Update(1,1,n); 91 R = e[i].r - e[i].l + 1; 92 int res = smt.Query(1,1,n); 93 if(res == e[i].l) ans[e[i].id] = 1; 94 else ans[e[i].id] = 0; 95 } 96 FOR(i,1,m){ 97 if(ans[i]) printf("YES\n"); 98 else printf("NO\n"); 99 } 100 } 101 return 0; 102 }