• 2018.10.20模拟总结


      离NOIP2018越来越近了,然而我仍有一些没有彻底弄懂的地方,有点慌,所以准备从这周开搞搞基础。

      不说别的了,先把这篇总结写完。

     

      Day1的题感觉不是很难,每一道题的暴力也都可写,总的来说难度跟noip差不多吧。

      有一个想吐槽的地方,就是为啥题目把算法都告诉了……

    T1 backpack

      期望得分:100

      实际得分:100

      正像题解所说,Day1T1是送分的。不过辛亏我以前做过一道类似的题,要不然只能得60。

      首先40分是送的,完全背包板子。然后发现尽管物品很多,但是体积和价值只有100。所以如果两件物品体积相同,那么就取价值更大的。所以实际上物品最多只有100个。然后一个O(100 * n)就得了60分。

      正解其实我也不知道为啥,不过以前做过一道搜索题,那道题数据范围特别大,但是除了暴力我实在想不出来该咋办,然后看题解时记住了这么一句话:“远距离贪心,近距离暴力”。到了这道题,就变成了“大容量贪心,小容量背包”。于是我们用性价比最高的物品填背包,直到剩余容量在1e5范围内,然后正常完全背包了。

    考场代码

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<cstdlib>
     7 #include<cctype>
     8 #include<vector>
     9 #include<stack>
    10 #include<queue>
    11 using namespace std;
    12 #define enter puts("") 
    13 #define space putchar(' ')
    14 #define Mem(a, x) memset(a, x, sizeof(a))
    15 #define rg register
    16 typedef long long ll;
    17 typedef double db;
    18 const int INF = 0x3f3f3f3f;
    19 const db eps = 1e-8;
    20 const int maxm = 1e5 + 5;
    21 inline ll read()
    22 {
    23     ll ans = 0;
    24     char ch = getchar(), last = ' ';
    25     while(!isdigit(ch)) {last = ch; ch = getchar();}
    26     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
    27     if(last == '-') ans = -ans;
    28     return ans;
    29 }
    30 inline void write(ll x)
    31 {
    32     if(x < 0) x = -x, putchar('-');
    33     if(x >= 10) write(x / 10);
    34     putchar(x % 10 + '0');
    35 }
    36 void MYFILE()
    37 {
    38 #ifndef mrclr
    39     freopen("backpack.in", "r", stdin);
    40     freopen("backpack.out", "w", stdout);
    41 #endif
    42 }
    43 
    44 int n;
    45 ll m;
    46 ll dp[maxm];
    47 int t[105];
    48 
    49 void work0()
    50 {
    51     ll ans = 0;
    52     int pos = 1;
    53     for(int i = 1; i <= 100; ++i) if((ll)t[i] * (ll)pos > (ll)t[pos] * (ll)i) pos = i;
    54     ll x = (m - maxm + (ll)pos - 1) / (ll)pos;
    55     m -= x * (ll)pos;
    56     ans += x * (ll)t[pos];    
    57 //    printf("@%lld
    ", ans);
    58     for(int i = 1; i <= 100; ++i)
    59         for(int j = i; j <= m; ++j)
    60             dp[j] = max(dp[j], dp[j - i] + t[i]);
    61     write(dp[m] + ans), enter;
    62 }
    63 
    64 int main()
    65 {
    66     MYFILE();
    67     n = read(); m = read();
    68     for(int i = 1; i <= n; ++i)
    69     {
    70         int x = read(), y = read();
    71         t[x] = max(t[x], y);
    72     }
    73     if(m > maxm) {work0(); return 0;}
    74     for(int i = 1; i <= 100; ++i)
    75         for(int j = i; j <= m; ++j)
    76             dp[j] = max(dp[j], dp[j - i] + t[i]);
    77 //    for(int j = 1; j <= m; ++j) printf("%lld ", dp[j]); enter;
    78     write(dp[m]), enter;
    79     return 0;
    80 }
    81 /*
    82 2 15
    83 3 2
    84 5 3
    85 */
    View Code

    T2 sort

      期望得分:100

      实际得分:100

      讲道理T2看了半天才把题看懂,因为我一直认为si可以等于tj,然后方案数总算不对。换然后看到题面说把{ci}分离成这两个序列,才觉得不对劲。如果对于任何 i和 j,都有si != sj ,那么样例就解释明白了:最大值一定是取sum[mid +1, r] - sum[l, mid];最小值一定是si和ti隔一个取一个。然后有这么个规律:对于当前的一个点x,si已经取到的数量一定大于等于ti取得数量。这个规律不就是括号匹配的方案数吗!答案就是卡特兰数呀。

      然后我就忘了卡特兰数的递推式了。只记得有一个C(n / 2, n),于是现场2n打表前10项,一顿神推竟然推出来了。不过忘了线性求逆元,于是O(nlogn)预处理。辛亏1e6没卡我这个。

      剩下的就是线段树维护区间和,奇偶和了。基本跟普通的线段树一样,不过虽然题目保证区间长度是偶数,但是线段树分治下去的不一定是奇数,所以pushdown的时候还要判断一下是奇数还是偶数累加的值比区间和的一半多1个,多了得补上。

      结果刚开始我没注意这个,以为是建树不对,又重写了一遍,就过更不对了。回头又改这个,这样就耽误了不少时间,导致T3没有多少时间了。

    还是考场代码

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cmath>
      4 #include<algorithm>
      5 #include<cstring>
      6 #include<cstdlib>
      7 #include<cctype>
      8 #include<vector>
      9 #include<stack>
     10 #include<queue>
     11 using namespace std;
     12 #define enter puts("") 
     13 #define space putchar(' ')
     14 #define Mem(a, x) memset(a, x, sizeof(a))
     15 #define rg register
     16 typedef long long ll;
     17 typedef double db;
     18 const int INF = 0x3f3f3f3f;
     19 const db eps = 1e-8;
     20 const ll mod = 1e9 + 7;
     21 const int maxn = 1e6 + 5;
     22 inline ll read()
     23 {
     24     ll ans = 0;
     25     char ch = getchar(), last = ' ';
     26     while(!isdigit(ch)) {last = ch; ch = getchar();}
     27     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
     28     if(last == '-') ans = -ans;
     29     return ans;
     30 }
     31 inline void write(ll x)
     32 {
     33     if(x < 0) x = -x, putchar('-');
     34     if(x >= 10) write(x / 10);
     35     putchar(x % 10 + '0');
     36 }
     37 void MYFILE()
     38 {
     39 #ifndef mrclr
     40     freopen("sort.in", "r", stdin);
     41     freopen("sort.out", "w", stdout);
     42 #endif
     43 }
     44 
     45 int n, m;
     46 
     47 ll quickpow(ll a, ll b)
     48 {
     49     a %= mod;
     50     ll ret = 1;
     51     while(b)
     52     {
     53         if(b & 1) ret = ret * a % mod;
     54         a  = a * a % mod; b >>= 1;
     55     }
     56     return ret;
     57 }
     58 ll fac[maxn], inv[maxn], cat[maxn];
     59 inline void init(const int& N)
     60 {
     61     fac[1] = 1;
     62     for(int i = 2; i <= N; ++i) fac[i] = fac[i - 1] * i % mod;
     63     inv[N] = quickpow(fac[N], mod - 2);
     64     for(int i = N - 1; i; --i) inv[i] = inv[i + 1] * (i + 1) % mod;
     65     ll x = 1;
     66     for(int i = 2; i <= N; i += 2)
     67     {
     68         x++;
     69         cat[i >> 1] = fac[i] * inv[i >> 1] % mod * inv[i >> 1] % mod * quickpow(x, mod - 2) % mod;
     70     }
     71 }
     72 
     73 int l[maxn << 2], r[maxn << 2];
     74 ll sum[maxn << 2], sum1[maxn << 2], sum0[maxn << 2], lzy[maxn << 2];
     75 void pushup(int now)
     76 {
     77     sum[now] = sum[now << 1] + sum[now << 1 | 1]; sum[now] %= mod;
     78     sum1[now] = sum1[now << 1] + sum1[now << 1 | 1]; sum1[now] %= mod;
     79     sum0[now] = sum0[now << 1] + sum0[now << 1 | 1]; sum0[now] %= mod;
     80 }
     81 void build(int L, int R, int now)
     82 {
     83     l[now] = L; r[now] = R;
     84     if(L == R)
     85     {
     86         sum[now] = read(); sum[now] %= mod;
     87         if(L & 1) sum1[now] = sum[now];
     88         else sum0[now] = sum[now];
     89         return;
     90     }
     91     int mid = (L + R) >> 1;
     92     build(L, mid, now << 1);
     93     build(mid + 1, R, now << 1 | 1);
     94     pushup(now);
     95 }
     96 void pushdown(int now)
     97 {
     98     if(lzy[now])
     99     {
    100         ll ha1 = (ll)(r[now << 1] - l[now << 1] + 1) * lzy[now];
    101         sum[now << 1] += ha1; sum[now << 1] %= mod;
    102         if((r[now << 1] - l[now << 1] + 1) & 1)
    103         {
    104             if(l[now << 1] & 1) sum1[now << 1] += lzy[now];
    105             else sum0[now << 1] += lzy[now];
    106         }
    107 //        if(l[now << 1] != r[now << 1] || (l[now << 1] == r[now << 1] && (l[now << 1] & 1)))
    108             sum1[now << 1] += (ha1 >> 1); sum1[now << 1] %= mod;
    109 //        if(l[now << 1] != r[now << 1] || (l[now << 1] == r[now << 1] && !(l[now << 1] & 1)))
    110             sum0[now << 1] += (ha1 >> 1); sum0[now << 1] %= mod;
    111         ll ha2 = (ll)(r[now << 1 | 1] - l[now << 1 | 1] + 1) * lzy[now];
    112         sum[now << 1 | 1] += ha2; sum[now << 1 | 1] %= mod;
    113         if((r[now << 1 | 1] - l[now << 1 | 1] + 1) & 1)
    114         {
    115             if(l[now << 1 | 1] & 1) sum1[now << 1 | 1] += lzy[now];
    116             else sum0[now << 1 | 1] += lzy[now];
    117         }    
    118 //        if(l[now << 1 | 1] != r[now << 1 | 1] || (l[now << 1 | 1] == r[now << 1 | 1] && (l[now << 1 | 1] & 1)))
    119             sum1[now << 1 | 1] += (ha2 >> 1); sum1[now << 1 | 1] %= mod;
    120 //        if(l[now << 1 | 1] != r[now << 1 | 1] || (l[now << 1 | 1] == r[now << 1 | 1] && !(l[now << 1 | 1] & 1)))
    121             sum0[now << 1 | 1] += (ha2 >> 1); sum0[now << 1 | 1] %= mod;
    122         lzy[now << 1] += lzy[now]; lzy[now << 1] %= mod;
    123         lzy[now << 1 | 1] += lzy[now]; lzy[now << 1] %= mod;
    124         lzy[now] = 0;
    125     }
    126 }
    127 void update(int L, int R, int now, int d)
    128 {
    129     if(L == l[now] && R == r[now])
    130     {
    131         ll ha = (ll)(R - L + 1) * d;
    132         sum[now] += ha; sum[now] %= mod;
    133         if((R - L + 1) & 1)
    134         {
    135             if(L & 1) sum1[now] += d;
    136             else sum0[now] += d;
    137         }
    138         sum1[now] += (ha >> 1); sum1[now] %= mod;
    139         sum0[now] += (ha >> 1); sum0[now] %= mod;
    140         lzy[now] += d; lzy[now] %= mod;
    141         return;
    142     }
    143     pushdown(now);
    144     int mid = (l[now] + r[now]) >> 1;
    145     if(R <= mid) update(L, R, now << 1, d);
    146     else if(L > mid) update(L, R, now << 1 | 1, d);
    147     else update(L, mid, now << 1, d), update(mid + 1, R, now << 1 | 1, d);
    148     pushup(now);
    149 }
    150 ll query(int L, int R, int now, int flg)
    151 {
    152     if(L == l[now] && R == r[now]) 
    153     {
    154         if(flg == 0) return sum0[now];
    155         else if(flg == 1) return sum1[now];
    156         else return sum[now];
    157     }
    158     pushdown(now);    
    159     int mid = (l[now] + r[now]) >> 1;
    160     if(R <= mid) return query(L, R, now << 1, flg);
    161     else if(L > mid) return query(L, R, now << 1 | 1, flg);
    162     else return (query(L, mid, now << 1, flg) + query(mid + 1, R, now << 1 | 1, flg)) % mod;
    163 }
    164 
    165 int main()
    166 {
    167     MYFILE();
    168     n = read(); m = read();
    169     init(n << 1);
    170     build(1, n << 1, 1);
    171     for(int i = 1; i <= m; ++i)
    172     {
    173         int d = read(), L = read(), R = read();
    174         if(d == 0)
    175         {
    176             int val = read();
    177             update(L, R, 1, val);
    178         }
    179         else
    180         {
    181             int mid = (L + R) >> 1;
    182             write((query(mid + 1, R, 1, 2) - query(L, mid, 1, 2) + mod) % mod), space;
    183             ll Min = query(L, R, 1, 0), Max = query(L, R, 1, 1);
    184             if(L & 1) swap(Min, Max);
    185             write((Max - Min + mod) % mod), space;
    186             write(cat[(R - L + 1) >> 1]), enter;
    187         }
    188     }
    189     return 0;
    190 }
    View Code

    T3 digit

      期望得分:0

      实际得分:0

      其实写暴力的时间还是有的,剩了40多分钟。主要原因是题没看懂:数位和到底是什么玩意儿!?样例模拟了半天还是不对,剩20多分钟的时候就放弃了,因为这点时间写生什么都来不及了,还不如检查T1,T2。

      现在发现T3部分分其实特别好拿。数位和就是这个数每一位上的数的和。所以30分暴力只要枚举k进制下L位到R位的所有数即可。

      50分是一个比较水的暴dp。题目数位dp纯粹和唬你的。因为4, 5, 6的最小公倍数是60,所以任何大于60的数只要对60取模就行了。令dp[i][j]表示到第 i 位,数位和 mod 60等于 j 的数的个数。那么就有dp[i][j] = Σdp[i - 1][j - h] (0 <= h < k)。因为j - h可能为负,所以代码应该写成(j - h % 60 + 60) % 60。最后的答案用前缀和的思想:ans = Σdp[R][i] - Σdp[L - 1][i],i 满足能被4,5,6其中一个整除。

      初始化应该是for(i : 0 ~k - 1) dp[1][i % 60]++。刚开始写成了dp[1][i] = 1。只得了20分,debug可好半天。

      满分做法:用矩乘优化。推转移矩阵的时候磨叽了好半天(还是不熟练,没理解透),最后还是看了std的代码。然后跑两遍快速幂。

    60分代码

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<cstdlib>
     7 #include<cctype>
     8 #include<vector>
     9 #include<stack>
    10 #include<queue>
    11 using namespace std;
    12 #define enter puts("") 
    13 #define space putchar(' ')
    14 #define Mem(a, x) memset(a, x, sizeof(a))
    15 #define rg register
    16 typedef long long ll;
    17 typedef double db;
    18 const int INF = 0x3f3f3f3f;
    19 const db eps = 1e-8;
    20 const ll mod = 1e9 + 7;
    21 const int maxn = 1e3 + 5;
    22 inline ll read()
    23 {
    24     ll ans = 0;
    25     char ch = getchar(), last = ' ';
    26     while(!isdigit(ch)) {last = ch; ch = getchar();}
    27     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
    28     if(last == '-') ans = -ans;
    29     return ans;
    30 }
    31 inline void write(ll x)
    32 {
    33     if(x < 0) x = -x, putchar('-');
    34     if(x >= 10) write(x / 10);
    35     putchar(x % 10 + '0');
    36 }
    37 void MYFILE()
    38 {
    39 #ifndef mrclr
    40     freopen("digit.in", "r", stdin);
    41     freopen("digit.out", "w", stdout);
    42 #endif
    43 }
    44 
    45 ll l, r, k;
    46 ll dp[maxn][65], ans = 0;
    47 
    48 int main()
    49 {
    50     MYFILE();
    51     l = read(); r = read(); k = read();
    52     if(r > 1000) return 0;
    53     for(rg int i = 0; i < k; ++i) dp[1][i % 60]++;
    54     for(rg int i = 2; i <= r; ++i)
    55         for(rg int j = 0; j < 60; ++j)
    56             for(rg int h = 0; h < k; ++h)
    57                 dp[i][j] += dp[i - 1][(j - h % 60 + 60) % 60], dp[i][j] %= mod;
    58     for(rg int i = 0; i < 60; ++i) 
    59         if(!(i % 4) || !(i % 5) || !(i % 6)) ans += dp[r][i] - dp[l - 1][i], ans %= mod;
    60     write((ans - (l == 1) + mod) % mod); enter;
    61     return 0;
    62 }
    View Code

    100分代码

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<cstdlib>
     7 #include<cctype>
     8 #include<vector>
     9 #include<stack>
    10 #include<queue>
    11 using namespace std;
    12 #define enter puts("") 
    13 #define space putchar(' ')
    14 #define Mem(a, x) memset(a, x, sizeof(a))
    15 #define rg register
    16 typedef long long ll;
    17 typedef double db;
    18 const int INF = 0x3f3f3f3f;
    19 const db eps = 1e-8;
    20 const ll mod = 1e9 + 7;
    21 const int N = 60;
    22 inline ll read()
    23 {
    24     ll ans = 0;
    25     char ch = getchar(), last = ' ';
    26     while(!isdigit(ch)) {last = ch; ch = getchar();}
    27     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
    28     if(last == '-') ans = -ans;
    29     return ans;
    30 }
    31 inline void write(ll x)
    32 {
    33     if(x < 0) x = -x, putchar('-');
    34     if(x >= 10) write(x / 10);
    35     putchar(x % 10 + '0');
    36 }
    37 void MYFILE()
    38 {
    39 #ifndef mrclr
    40     freopen("digit.in", "r", stdin);
    41     freopen("digit.out", "w", stdout);
    42 #endif
    43 }
    44 
    45 ll l, r, k, ans = 0;
    46 
    47 struct Mat
    48 {
    49     ll a[N + 5][N + 5];
    50     Mat operator * (const Mat &oth)const
    51     {
    52         Mat ret; Mem(ret.a, 0);
    53         for(int i = 0; i < N; ++i)
    54             for(int j = 0; j < N; ++j)
    55                 for(int k = 0; k < N; ++k)
    56                     ret.a[i][j] = (ret.a[i][j] + a[i][k] * oth.a[k][j]) % mod;
    57         return ret;
    58     }
    59 }f;
    60 
    61 Mat quickpow(Mat A, ll b)
    62 {
    63     Mat ret; Mem(ret.a, 0);
    64     for(int i = 0; i < 60; ++i) ret.a[i][i] = 1;
    65     while(b)
    66     {
    67         if(b & 1) ret = ret * A;
    68         A = A * A; b >>= 1;
    69     }
    70     return ret;
    71 }
    72 
    73 int main()
    74 {
    75     MYFILE();
    76     ll l = read(), r = read(), k = read();
    77     Mem(f.a, 0);
    78     for(int i = 0; i < N; ++i)
    79     {
    80         for(int j = 0; j < N; ++j)
    81             f.a[i][j] = k / N % mod;
    82         for(int j = 0; j < k % N; ++j)
    83             f.a[i][(i + j) % N]++, f.a[i][(i + j) % N] %= mod;
    84     }
    85     Mat A = quickpow(f, r);
    86     for(int i = 0; i < N; ++i)
    87         if(!(i % 4) || !(i % 5) || !(i % 6)) ans = (ans + A.a[0][i]) % mod;
    88     A = quickpow(f, l - 1);
    89     for(int i = 0; i < N; ++i)
    90         if(!(i % 4) || !(i % 5) || !(i % 6)) ans = (ans - A.a[0][i] + mod) % mod;
    91     write(ans), enter;
    92     return 0;
    93 }
    View Code

      Day1美中不足的地方在于T2花费的时间有点多,而这是因为没有思考周全就开始写代码了,写完后就没有自信,然后有点盲目的改,结果浪费了不少时间。

  • 相关阅读:
    Repeater 中 OnItemCommand 用法
    正则匹配 替换..追加..
    Jquery validform
    MSSQL执行大脚本文件时,提示“内存不足”的解决办法
    获取表达式属性名称
    动态查询框架
    领域事件相关文章
    在微服务中使用领域事件(转载)
    Java核心编程快速学习(转载)
    面向对象编程思想(前传)--你必须知道的javascript(转载)
  • 原文地址:https://www.cnblogs.com/mrclr/p/9826713.html
Copyright © 2020-2023  润新知