181020-181021 模拟 题解

Day1

总体状态自认为不错....但是T1读错题了就很难受

以后一定要看清楚所有的细节再写题 因为不一定什么细节就能改变所有的思路

T2 Debug 70+min...其实就是细节的问题(二分边界)

所以写代码的时候一定要考虑周全

Think twice,code once.

 

T1 backpack 60/100

Time cost :15min

怎么可能把算法在题面里说出来啊...

天真的以为m<=1e6然后开心的O(a*m)结束..

题解里面有个结论 就是体积极大的时候可以贪心选性价比最高的到一定程度

题解用抽屉原理证了一下 这个其实考试的时候可以想成一直选到m<=1e5再做背包

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cmath>
 4 #include <iostream>
 5 #include<algorithm>
 6 #define rep(i,a,n) for(int i = a;i <= n;++i)
 7 #define per(i,n,a) for(int i = n;i >= a;--i)
 8 #define inf 2147483647
 9 #define ms(a,b) memset(a,b,sizeof a)
10 using namespace std;
11 typedef long long ll;
12 ll read() {
13     ll as = 0,fu = 1;
14     char c = getchar();
15     while(c < '0' || c > '9') {
16     if(c == '-') fu = -1;
17     c = getchar();
18     }
19     while(c >= '0' && c <= '9') {
20     as = as * 10 + c - '0';
21     c = getchar();
22     }
23     return as * fu;
24 }
25 //head
26 const int N = 100005;
27 ll n,m,maxid;
28 ll a[105],dp[N];
29 
30 int main() {
31     freopen("backpack.in","r",stdin);
32     freopen("backpack.out","w",stdout);
33     n = read(),m = read();
34     rep(i,1,n) {
35         int x = read();
36         a[x] = max(a[x],read());
37     }
38     rep(x,1,100) {
39         if(!maxid || a[x] * maxid > a[maxid] * x) maxid = x;
40     }
41     ll cnt = (m - 1e5) / maxid;
42     ll ans = cnt * a[maxid];
43     m -= cnt * maxid;
44     dp[0] = 0;
45     rep(i,1,100) {
46         rep(j,i,m) {
47             dp[j] = max(dp[j],dp[j-i]+a[i]);
48         }
49     }
50     printf("%lld\n",dp[m]+ans);
51     return 0;
52 }

 

 

T2 sort 100/100

Time cost : 130min

写代码不注意细节...亏大了

当时大样例要是改不过来就爆0

思路就是首先需要看出来(或者证出来)

最大值是前后一半

最小值是交叉

方案数是Catalan(因为是转化后的括号序列)

不知道为什么不少人看不出来...之前还一起研究来着

Catalan可以O(n)预处理O(1)做

关键就是交叉这个需要开两个长为n的线段树分别维护奇偶位置上的值

然后最大值就特别恶心

(最后题解开了3棵线段树...)

Code:

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cmath>
  6 #include<queue>
  7 #include<vector>
  8 #define ms(a,b) memset(a,b,sizeof a)
  9 #define rep(i,a,n) for(int i = a;i <= n;++i)
 10 #define per(i,n,a) for(int i = n;i >= a;--i)
 11 #define inf 2147483647
 12 using namespace std;
 13 typedef long long ll;
 14 ll read() {
 15     ll as = 0,fu = 1;
 16     char c = getchar();
 17     while(c < '0' || c > '9') {
 18         if(c == '-') fu = -1;
 19         c = getchar();
 20     }
 21     while(c >= '0' && c <= '9') {
 22         as = as * 10 + c - '0';
 23         c = getchar();
 24     }
 25     return as * fu;
 26 }
 27 const int N = 1000005;
 28 const int mod = 1e9+7;
 29 //head
 30 int n;
 31 ll a[N];
 32 ll stp[N],stq[N];
 33 ll ksm(ll a,ll b,ll p) {
 34     ll tmp = 1;
 35     while(b) {
 36         if(b & 1) tmp = tmp * a % p;
 37         a = a * a % p;
 38         b >>= 1;
 39     }
 40     return tmp;
 41 }
 42 
 43 ll fac[N],inv[N];
 44 void initfac() {
 45     fac[0] = inv[0] = inv[1] = 1;
 46     rep(i,1,n<<1) fac[i] = fac[i-1] * i % mod;
 47     inv[n<<1] = ksm(fac[n<<1],mod - 2,mod);
 48     per(i,(n<<1)-1,2) inv[i] = inv[i+1] * (i+1) % mod;
 49 }
 50 
 51 ll Catalan(int n) {
 52     return fac[n<<1] * inv[n+1] % mod * inv[n] % mod;
 53 }
 54 
 55 ll p[N<<2],q[N<<2];
 56 ll addp[N<<2],addq[N<<2];
 57 #define ls t<<1
 58 #define rs t<<1|1
 59 void pup(int t) {
 60     p[t] = (p[ls] + p[rs]) % mod;
 61 }
 62 
 63 void pdown(int l,int r,int t) {
 64     if(!addp[t]) return;
 65     int m = l+r >> 1;
 66     int szl = m+1-l,szr = r-m;
 67     p[ls] = (p[ls] + addp[t] * szl) % mod;
 68     p[rs] = (p[rs] + addp[t] * szr) % mod;
 69     addp[ls] = (addp[t] + addp[ls]) % mod;
 70     addp[rs] = (addp[t] + addp[rs]) % mod;
 71     addp[t] = 0;
 72 }
 73 
 74 void qup(int t) {
 75     q[t] = (q[ls] + q[rs]) % mod;
 76 }
 77 
 78 void qdown(int l,int r,int t) {
 79     if(!addq[t]) return;
 80     int m = l+r >> 1;
 81     int szl = m+1-l,szr = r-m;
 82     q[ls] = (q[ls] + addq[t] * szl) % mod;
 83     q[rs] = (q[rs] + addq[t] * szr) % mod;
 84     addq[ls] = (addq[ls] + addq[t]);
 85     addq[rs] = (addq[rs] + addq[t]);
 86     addq[t] = 0;
 87 }
 88 
 89 void build(int l,int r,int t) {
 90     if(l == r) {
 91         p[t] = stp[l];
 92         q[t] = stq[l];
 93         return;
 94     }
 95     int m = l+r >> 1;
 96     build(l,m,ls),build(m+1,r,rs);
 97     pup(t),qup(t);
 98 }
 99 
100 void update(int L,int R,ll c,int l,int r,int t,bool op) {
101     if(L > R) return;
102     if(L <= l && r <= R) {
103         if(op) {
104             p[t] = (p[t] + c * (r-l+1)) % mod;
105             addp[t] = (addp[t] + c) % mod;
106         } else {
107             q[t] = (q[t] + c * (r-l+1)) % mod;
108             addq[t] = (addq[t] + c) % mod;
109         }
110         return;
111     }
112     pdown(l,r,t),qdown(l,r,t);
113     int m = l+r >> 1;
114     if(L <= m) update(L,R,c,l,m,ls,op);
115     if(R > m) update(L,R,c,m+1,r,rs,op);
116     pup(t),qup(t);
117 }
118 
119 ll query(int L,int R,int l,int r,int t,bool op) {
120     if(L > R) return 0;
121     if(L <= l && r <= R) return op ? p[t] : q[t];
122     pdown(l,r,t),qdown(l,r,t);
123     int m = l+r >> 1;
124     ll ans = 0;
125     if(L <= m) ans = (ans + query(L,R,l,m,ls,op)) % mod;
126     if(R >  m) ans = (ans + query(L,R,m+1,r,rs,op)) % mod;
127     return ans;
128 }
129 
130 #define idx(i) (((i)+1)>>1)
131 int main() {
132     freopen("sort.in","r",stdin);
133     freopen("sort.out","w",stdout);
134     n = read();
135     int T = read();
136     rep(i,1,n<<1) a[i] = read();
137     rep(i,1,n) {
138         stp[i] = a[(i<<1)-1];
139         stq[i] = a[i<<1];
140     }
141     initfac(),build(1,n,1);
142     while(T--) {
143         int op = read(),x = read(),y = read();
144         if(op) {
145             ll maxx,minn,Cat;
146             int m = x+y >> 1;
147             if((x & 1) == (m & 1)) {
148                 maxx = query(idx(m+1),idx(y),1,n,1,y&1) + query(idx(m+2),idx(y-1),1,n,1,x&1);
149                 maxx = maxx - query(idx(x),idx(m),1,n,1,x&1) - query(idx(x+1),idx(m-1),1,n,1,y&1);
150             } else {
151                 maxx = query(idx(m+2),idx(y),1,n,1,y&1) + query(idx(m+1),idx(y-1),1,n,1,x&1);
152                 maxx = maxx - query(idx(x),idx(m-1),1,n,1,x&1) - query(idx(x+1),idx(m),1,n,1,y&1);
153             }
154             maxx = (maxx % mod + mod) % mod;
155             minn = query(idx(x+1),idx(y),1,n,1,(y&1)) - query(idx(x),idx(y-1),1,n,1,(x&1));
156             minn = (minn % mod + mod) % mod;
157             Cat = Catalan(y-x+1>>1);
158             printf("%lld %lld %lld\n",maxx,minn,Cat);
159         } else {
160             ll k = read();
161             update(idx(x),idx(y-1),k,1,n,1,(x&1));
162             update(idx(x+1),idx(y),k,1,n,1,(y&1));
163         }
164     }
165     return 0;
166 }

 

T3 digit 0/100

超级水的dp...如果心态稳一点或者代码仔细一点说不定真能AK...

50思路就是f[i][j]表示i位mod60余j有多少种情况( 60 == lcm(4,5,6) )

所以f[i][j] = ∑f[i-1][l](0<=l<k) f[0][0]=0

然后就是一个显然的矩阵乘法

发现自己会矩阵乘法 但是每次都是线性Dp不出来....

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<queue>
 6 #include<vector>
 7 #define C continue
 8 #define B break
 9 #define ms(a,b) memset(a,b,sizeof a)
10 #define rep(i,a,n) for(int i = a;i <= n;i++)
11 #define per(i,n,a) for(int i = n;i >= a;i--)
12 #define inf 3e10
13 using namespace std;
14 typedef long long ll;
15 ll read() {
16     ll as = 0,fu = 1;
17     char c = getchar();
18     while(c < '0' || c > '9') {
19         if(c == '-') fu = -1;
20         c = getchar();
21     }
22     while(c >= '0' && c <= '9') {
23         as = as * 10 + c - '0';
24         c = getchar();
25     }
26     return as * fu;
27 }
28 const int N = 60;
29 const ll mod = 1e9+7;
30 //head
31 struct Mt {
32     ll a[N][N];
33     void init(bool op) {
34         ms(a,0);
35         rep(i,0,N-1) a[i][i] = op;
36     }
37     Mt operator * (const Mt &o) const {
38         Mt tmp;tmp.init(0);
39         rep(i,0,N-1) rep(j,0,N-1) rep(k,0,N-1) {
40             tmp.a[i][j] = (tmp.a[i][j] + (ll)a[i][k] * o.a[k][j] % mod) % mod;
41         }
42         return tmp;
43     }
44     Mt operator ^ (ll b) const {
45         Mt tmp;tmp.init(1);
46         Mt t = *this;
47         while(b) {
48             if(b & 1) tmp = tmp * t;
49             t = t * t;
50             b >>= 1;
51         }
52         return tmp;
53     }
54 }str,res;
55 bool judge(int x) {
56     if(x % 4 == 0) return 1;
57     if(x % 5 == 0) return 1;
58     if(x % 6 == 0) return 1;
59     return 0;
60 }
61 ll l,r,k,ans;
62 
63 int main() {
64     freopen("digit.in","r",stdin);
65     freopen("digit.out","w",stdout);
66     l = read(),r = read(),k = read();
67     str.init(0);
68     rep(i,0,N-1) {
69         rep(j,0,N-1) str.a[j][i] = k / N % mod;
70         rep(j,0,k % N - 1) str.a[(i + j) % N][i]++;
71     }
72     
73     res = str ^ r;
74     rep(i,0,N-1)
75         if(judge(i)) ans = (ans + res.a[i][0]) % mod;
76     
77     res = str ^ (l-1);
78     rep(i,0,N-1)
79         if(judge(i)) ans = (ans + mod - res.a[i][0]) % mod;
80     printf("%lld\n",ans);
81     return 0;
82 }

 

Day2 

三道题都不会...

最后gangT1没gang过还交错了...

T1 median

其实考试的时候思路基本出来了...但是还是二分边界不熟...

做法是先假设答案在a序列里

二分a中的点(答案?) 可以得出如果这个点是答案那么应该在b中排第几

如果对的话就是答案 否则就往左右跳

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cmath>
 4 #include <iostream>
 5 #include<algorithm>
 6 #define rep(i,a,n) for(int i = a;i <= n;++i)
 7 #define per(i,n,a) for(int i = n;i >= a;--i)
 8 #define inf 2147483647
 9 #define ms(a,b) memset(a,b,sizeof a)
10 using namespace std;
11 typedef long long ll;
12 ll read() {
13     ll as = 0,fu = 1;
14     char c = getchar();
15     while(c < '0' || c > '9') {
16     if(c == '-') fu = -1;
17     c = getchar();
18     }
19     while(c >= '0' && c <= '9') {
20     as = as * 10 + c - '0';
21     c = getchar();
22     }
23     return as * fu;
24 }
25 //head
26 const int N = 500005;
27 int n,m,ans;
28 int a[N],b[N];
29 
30 int calc(int *a,int *b,int l1,int r1,int l2,int r2) {
31     int Rnk = r1 - l1 + 1 + r2 - l2 + 1 >> 1,l = l1,r = r1;
32     while(l <= r) {
33     int m = l+r >> 1;
34     int rnkb = Rnk - (m-l1+1) + l2;
35     if(rnkb == l2 - 1 && Rnk == m-l1 && a[m] <= b[l2]) return a[m];
36     else if(rnkb < l2) r = m - 1;
37     else if(rnkb > r2) l = m + 1;
38     else if(a[m] >= b[rnkb] && (a[m] <= b[rnkb+1] || rnkb == r2)) return a[m];
39     else if(a[m] >= b[rnkb]) r = m-1;
40     else l = m+1;
41     }
42     return 0;
43 }
44 
45 
46 int main() {
47     freopen("median.in","r",stdin);
48     freopen("median.out","w",stdout);
49     n = read(),m = read();
50     rep(i,1,n) a[i] = read();
51     rep(i,1,n) b[i] = read();
52     rep(i,1,m) {
53     int op = read(); 
54     if(op == 1) {
55         int x = read(),y = read(),z = read();
56         x ? b[y] = z : a[y] = z;
57     } else {
58         int l1 = read(),r1 = read(),l2 = read(),r2 = read();
59         if(ans = calc(a,b,l1,r1,l2,r2)) printf("%d\n",ans);
60         else printf("%d\n",calc(b,a,l2,r2,l1,r1));
61     }
62     }
63     return 0;
64 }
65  

 

转载于:https://www.cnblogs.com/yuyanjiaB/p/9834025.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值