zoukankan      html  css  js  c++  java
  • 2019-08-20 纪中NOIP模拟B组

    T1 [JZOJ3490] 旅游(travel)

    题目描述

      ztxz16如愿成为码农之后,整天的生活除了写程序还是写程序,十分苦逼。终于有一天,他意识到自己的生活太过平淡,于是决定外出旅游丰富阅历。

      ztxz16生活的城市有N*M个景点,可以描述成一个N*M的矩形,每个景点有一个坐标(x, y) (1 <= x <= N, 1 <= y <= M)以及美观度A[x][y]和观赏所需的时间B[x][y],从一个景点(x1, y1)走到另一个景点(x2, y2)需要时间为它们之间的曼哈顿距离:|x1 - x2| + |y1 - y2|。

      为了防止审美疲劳,ztxz16希望观赏的景点的的美观度是严格上升的,由于不想太早回家码代码,ztxz16希望旅游的总时间尽可能长。

    数据范围

      对于 $30\%$ 的数据,$1 leq N,M leq 50$

      对于 $60\%$ 的数据,$1 leq N,M leq 300$

      对于 $100\%$ 的数据,$1 leq N,M leq 1000$,$0 leq A leq 10^6$,$0 leq B leq 10^9$

    分析

      数据较水,$O(n^2m^2)$ 可以过,暂没写出 $O(nm)$ 做法

    T2 [JZOJ3491] 做梦(dream)

    题目描述

      ztxz16旅游归来后十分疲倦,很快就进入了梦中。

      在梦中ztxz16结婚生子了,他不得不照顾小宝宝。但这实在太无聊了,于是ztxz16会在散步。梦中ztxz16住在一个类似数轴的街上,数轴上的每个整点是一个街区,每个单位时间内ztxz16可以选择向左走一个街区或者向右走一个街区,但如果他离开家超过m个单位时间小宝宝会有危险,因此ztxz16必须在距离上次在家中不超过m个单位时间内回到家中。n个单位时间后ztxz16会醒来,他希望此时正好在家中。

      ztxz16想知道散步过程可能有多少种不同的散步过程。两个散步过程被认为不同,当且仅当存在至少一个单位时刻ztxz16选择的走向不同。

    数据范围

      对于 $30\%$ 的数据,$2 leq N leq 100$,$2 leq M leq 100$

      对于 $100\%$ 的数据,$2 leq N leq 10^9$,$2 leq M leq 100$

      $N$ 和 $M$ 均为偶数

    分析

      看到数据,很容易想到矩阵乘法

      设 $f[i][j]$ 表示不经过起点走 $i$ 步到达 $j$ 位置的不同路径数

      于是可以推出初始矩阵为 $$egin{bmatrix} 0 & 0 & cdotcdotcdot & 0 & f[frac{m}{2}]\ 1 & 0 & cdotcdotcdot & 0 & f[frac{m}{2}-1]\ 0 & 1 & cdotcdotcdot & 0 & f[frac{m}{2}-2]\ cdotcdotcdot & cdotcdotcdot & cdotcdotcdot & cdotcdotcdot & cdotcdotcdot\ 0 & 0 & cdotcdotcdot & 0 & f[2]\ 0 & 0 & cdotcdotcdot & 1 & f[1] end{bmatrix}$$

      然后只需要求出矩阵 $frac{n}{2}$ 次幂的最后一项就可以了

      (关于这样转移的原因,手推一下前几个矩阵找出最后一项的形成规律就好了,而且也会明白为什么 $f$ 数组记录的是不经过起点的路径数)

    #include <iostream>
    #include <cstdio>
    #include <cstdlib> 
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <queue>
    using namespace std;
    #define ll long long
    #define inf 0x3f3f3f3f
    
    int n, m, ans;
    int f[105][105];
    int p = 1e9 + 7;
    
    struct Mat {
        int t[55][55];
        Mat() {memset(t, 0, sizeof t);}
    } x;
    
    Mat Mul(Mat a, Mat b) {
        Mat c;
        for (int i = 1; i <= m; i++)
        for (int j = 1; j <= m; j++)
        for (int k = 1; k <= m; k++)
            c.t[i][j] = (c.t[i][j] + (ll)a.t[i][k] * b.t[k][j] % p) % p;
        return c;
    }
    
    Mat Pow(Mat a, int b) {
        Mat c;
        for (int i = 1; i <= m; i++) c.t[i][i] = 1;
        while (b) {
            if (b & 1) c = Mul(c, a);
            a = Mul(a, a); b >>= 1;
        }
        return c;
    }
    
    int main() {
        scanf("%d%d", &n, &m);
        n >>= 1; m >>= 1;
        f[1][m - 1] = f[1][m + 1] = 1;
        for (int i = 2; i <= (m << 1); i++)
            for (int j = 0; j <= (m << 1); j++) {
                if (j - 1 != m) f[i][j] = (f[i][j] + f[i - 1][j - 1]) % p;
                if (j + 1 != m) f[i][j] = (f[i][j] + f[i - 1][j + 1]) % p;
            }
        for (int i = 2; i <= m; i++) x.t[i][i - 1] = 1;
        for (int i = 1; i <= m; i++) x.t[m + 1 - i][m] = f[i << 1][m];
        x = Pow(x, n);
        printf("%d", x.t[m][m]);
        
        return 0;
    }
    View Code

    T3 [JZOJ3492] 数数(count)

    题目描述

      ztxz16从小立志成为码农,因此一直对数的二进制表示很感兴趣。今天的数学课上,ztxz16学习了等差数列的相关知识。我们知道,一个等差数列可以用三个数A,B,N表示成如下形式:

      B + A, B + 2 * A, B + 3 * A, ..., B + N * A

      ztxz16想知道对于一个给定的等差数列,把其中每一项用二进制表示后,一共有多少位是1,但他的智商太低无法算出此题,因此寻求你的帮助。

    数据范围

      对于 $30\%$ 的数据,$1 leq T leq 20$,$1 leq A leq 10^4$,$1 leq B leq 10^{16}$,$1 leq N leq 10^3$

      对于 $60\%$ 的数据,$1 leq T leq 20$,$1 leq A leq 10^4$,$1 leq B leq 10^{16}$,$1 leq N leq 10^9$

      对于 $100\%$ 的数据,$1 leq T leq 20$,$1 leq A leq 10^4$,$1 leq B leq 10^{16}$,$1 leq N leq 10^{12}$

    分析

      对于一个二进制数 $x$,它第 $k$ 位上的数为 $lfloor frac{x}{2^{k-1}} floor - lfloor frac{x}{2^k} floor imes 2$

      所以在等差数列的 $n$ 个数中,第 $k$ 位的总贡献为 $sum_{i=1}^n lfloor frac{b+ai}{2^{k-1}} floor - lfloor frac{b+ai}{2^k} floor imes 2$

      最后答案就是每一位上的贡献之和

      对于形如 $f(a,b,c,n)=sum_{i=0}^n lfloor frac{ai+b}{c} floor$ 的式子,我们会使用类欧几里得算法来计算

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <vector>
    #include <queue>
    using namespace std;
    #define ll long long
    #define inf 0x3f3f3f3f
    
    ll T, A, B, N, f[65];
    
    ll calc(ll a, ll b, ll c, ll n) {
        if (!a) return b / c * (n + 1);
        if (a < c && b < c) {
            ll m = (a * n + b) / c;
            if (!m) return 0;
            return n * m - calc(c, c - b - 1, a, m - 1);
        }
        if (n & 1)
        return calc(a % c, b % c, c, n) + (n + 1) / 2 * n * (a / c) + (n + 1) * (b / c);
        return calc(a % c, b % c, c, n) + n / 2 * (n + 1) * (a / c) + (n + 1) * (b / c);
    }
    
    int main() {
        scanf("%lld", &T);
        while (T--) {
            ll ans = 0;
            scanf("%lld%lld%lld", &A, &B, &N);
            for (ll i = 1, j = 0; (i >> 1) <= B + A * N; i <<= 1, j++)
                f[j] = calc(A, B + A, i, N - 1);
            for (ll i = 1, j = 0; i <= B + A * N; i <<= 1, j++)
                ans += f[j] - (f[j + 1] << 1);
            printf("%lld
    ", ans);
        }
        
        return 0;
    }
    View Code
  • 相关阅读:
    firewall
    mtu测试
    bps和pps
    PC上装VM上装虚拟机
    jira添加工作流
    【Linux系列】Centos 7安装 PHP(四)
    【Linux系列】Centos 7安装 Nginx(三)
    【Linux系列】配置Centos 7的软件源(二)
    【Linux系列】Centos 7安装以及网络配置(一)
    Python3获取豆瓣图书标签的前20本热门书籍(一)
  • 原文地址:https://www.cnblogs.com/Pedesis/p/11385878.html
Copyright © 2011-2022 走看看