10.2模拟赛总结

Posted spbv587

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了10.2模拟赛总结相关的知识,希望对你有一定的参考价值。

10.2 模拟赛总结

T1.

技术图片

数位dp:

一个非常非常非常非常显然的数位 DP

\\([L,R] = [1,R]-[1,L-1]\\)

所以是分别求两次小于等于某个数字的方案数

\\(f(i,j,k)\\) 表示从低位数起的第 \\(i\\) 位,按照规则计算后答案为 \\(j\\quad (j=0,1)\\)

\\(k\\) 表示只考虑后面结尾和 \\(lmt\\)后面几位 的大小关系 \\((k=0,1)\\)

考虑第 \\(i+1\\) 位,算一下新构成的数字并判断下大小就可以了

注意到 \\(L,R\\) 数据范围特别大,需要用高精度,最后结果要以二进制输出,所以可以对高精度压位

(以上扒的题解)

这题是个正常人就会想到找规律:

然后就有打表:(1~100)

技术图片

技术图片

然后就没了(啥?还有高精呢)

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#define LL long long
using namespace std;
int n, q, v,  t, L, R, len;
char s[208];
struct bigint

    int len, zz;
    int v[1005];
    bigint()len = 0; memset(v, 0, sizeof v); zz = 1;
    bigint(int x)
    
        if(x >= 0) zz = 1;
        else x = -x, zz = 0;
        len = 0;
        memset(v, 0, sizeof v);
        while(x)
        
            v[ ++len] = x % 10;
            x /= 10;
        
    
    friend bool operator < (const bigint &a, const bigint &b)
    
        if(a.len < b.len) return 1;
        if(a.len > b.len) return 0;
        for(int i = a.len ; i >= 1; i -- )
        
            if(a.v[i] < b.v[i]) return 1;
            if(a.v[i] > b.v[i]) return 0;
        
        return 0;
    
    friend bool operator == (const bigint &a, const bigint &b)
    
        if(a.len != b.len ) return 0;
        for(int i = a.len; i >= 1; i --)
        
            if(a.v[i] != b.v[i]) return 0;
        
        return 1;
    
    friend bool operator <= (const bigint &a, const bigint &b)
    
        if(a < b) return 1;
        else if(a == b) return 1;
        else return 0;
    
    friend bool operator != (const bigint &a, const bigint &b)
    
        if(a.len != b.len) return 1;
        for(int i = a.len; i >= 1; i --)
        
            if(a.v[i] != b.v[i]) return 1;
        
        return 0;
    
x, y, res;
bigint operator + (bigint a, bigint b)

    int len = a.len + b.len;
    bigint c;
    c.len = len;
    for(int i = 1; i <= len; i ++)
     c.v[i] = a.v[i] + b.v[i];
    for(int i = 1; i <= len; i ++)
    
        if(c.v[i] >= 10)
        
            ++c.v[i+1];
            c.v[i] -= 10;
        
    
    while(c.len&&!c.v[c.len]) c.len --;
    return c;

bigint operator - (bigint a, bigint b)

    int len = max(a.len, b.len);
    bigint c;
    for(int i = 1; i <= len; i ++)
    c.v[i] = a.v[i] - b.v[i];
    c.len = len;
    for(int i = 1; i <= c.len; i ++)
    
        if(c.v[i] < 0)
        
            c.v[i+1]--;
            c.v[i] += 10;
        
    
    while(c.len&&!c.v[c.len]) c.len --;
    return c;

bigint operator *(bigint a,bigint b)

    bigint c;
    for(int i = 1; i <= a.len; ++ i)
    for(int j = 1; j <= b.len; ++ j)
    c.v[i+j-1] += a.v[i] * b.v[j];
    c.len = a.len + b.len;
    for(int i = 1;  i <= c.len - 1; ++ i)
    
        if(c.v[i] >= 10)
        
            c.v[i+1] += c.v[i] / 10;
            c.v[i] %= 10;
        
    
    while(c.v[c.len] == 0&&c.len > 1) -- c.len;
    return c;

bigint operator /(bigint a,long long b)

    bigint c;int d = 0;
    for(int i = a.len; i >= 1; -- i)
    c.v[++ c.len] = ((d * 10 + a.v[i]) / b),d=(d*10+a.v[i])%b;
    for(int i=1;i<=c.len/2;++i)swap(c.v[i],c.v[c.len-i+1]);
    while(c.v[c.len]==0&&c.len>1)--c.len;
    return c;

bigint Min(bigint a, bigint b)

    if(a < b) return a;
    else return b;

bigint work(bigint x)

    if(x < bigint(4)) return bigint(1);
    bigint l = bigint(4), r = Min(x, bigint(7)), res = bigint(1);
    int opt = 1;
    for(; ; l = r + bigint(1), r = Min(r * bigint(2)  + bigint(1), x), opt ^= 1 )
    
        if(opt)
          res = res + (r - l + bigint(1));
          if(r == x) break;
    
    return res;

void out(bigint x)

    if(!x.len) return (void)printf("0");
    bigint qwq = bigint(1);
    while(qwq <= x) qwq = qwq * bigint(2);
    qwq = qwq / 2;
    for(; ; qwq = qwq /2)
    
        if(qwq <= x)
        
            printf("1");
            x = x - qwq;
        
        else printf("0");
        if(qwq == bigint(1))break;
       

void solve()

    x = y = res = bigint(0);
    scanf("%s", s + 1);
    for(int i = 1; i <= n; i ++)
    
        x = x * 2 + bigint(s[i] - '0');
    
    scanf("%s", s + 1);
    for(int i = 1; i <= n; i ++)
    
        y = y * 2 + bigint(s[i] - '0');
    
    res = work(y) - work(x - bigint(1));
    if((n&1) == (q&1)) res = y - x + 1 - res;
    out(res);
    puts("");

signed main()

//  freopen("a.in", "r", stdin);
//  freopen("a.out", "w", stdout);
    scanf("%d", &t);
    while(t --)
    
        scanf("%d%d",&n, &q);
        solve();
    
    return 0;

T2

技术图片

一sb题, 没啥总结的。。技术图片

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#define LL long long
#define N 100005
using namespace std;
struct node

    int w1, w2, l1, l2;
q[N];
int n, m, t, minw = 2e9, maxw = -233, minl = 2e9, maxl = -233, flag; 
signed main()

    freopen("b.in", "r",stdin);
    freopen("b.out", "w", stdout);
    scanf("%d", &t);
    while(t -- )
    
        flag = 0; minw = minl = 2e9; maxw = maxl = -233;
        scanf("%d", &n);
        for(int i = 1; i <= n; i ++)
            scanf("%d%d%d%d", &q[i].w1, &q[i].w2, &q[i].l1, &q[i].l2);
        for(int i = 1; i <= n; i ++)
        
            minw = min(minw, q[i].w1);
            maxw = max(maxw, q[i].w2);
            minl = min(minl, q[i].l1);
            maxl = max(maxl, q[i].l2);
        
        for(int i = 1; i <= n; i ++)
        
            if(q[i].w1 <= minw&&q[i].w2 >= maxw&&q[i].l1 <= minl&&q[i].l2 >= maxl)
            flag = 1; break; 
        
        if(flag)printf("TAK\\n");
             else printf("NIE\\n");
    
    return 0;

T3

技术图片

毒瘤数据结构+数论题

--给定1, n, d, v 给序列所有满足\\(gcd(x, n)=d\\)\\(x\\), 给\\(a[x]+=v\\);

就相当于\\(a[x]+=v[gcd(x, n)==d]\\)

然后就可以愉快的推式子了

\\(\\ \\ \\ \\ v[\\gcd(x,n) = d]\\)

$ = v [\\gcd(\\fracxd,\\fracnd)=1]$

$ = v\\sum\\limits_k|\\gcd(\\fracxd,\\fracnd) \\mu(k)$ (日常反演)

$ = v\\sum\\limits_k|\\fracxd,k|\\fracnd \\mu(k)$

\\(=\\sum\\limits_k|\\fracnd,kd|x v\\mu(k)\\)

暴力做法显然是要枚举\\(x\\), 对于每一个\\(k|\\fracnd且kd|x\\), 都加上\\(v\\mu(k)\\),

可以等价于

对于一个合法的\\(k|\\dfracnd\\), 则\\(x =kd,2kd,3kd...\\), 枚举\\(k\\), 把所有\\(kd\\), 的倍数都加上\\(v\\mu(k)\\);

这样虽然\\(O(1)\\)查询, 但修改的复杂度太大

考虑均摊复杂度

我们开一个数组\\(f\\) 表示所有是\\(i\\), 的倍数的位置都加上\\(f[i]\\)

修改时只需找出合法的\\(k\\), 然后\\(f[kd]+=v\\mu(k)\\), 省去了枚举\\(kd\\) 的倍数;

然后查询时 查询一个数\\(i\\) 时, 就成了\\(\\sum_d|if(d)\\)

\\(x\\), 的前缀和就是

\\(\\sum\\limits_i=1^x\\sum\\limits_d|i f(d)=\\sum\\limits_d=1^x f(d)\\lfloor \\fracxd\\rfloor\\)

然后就可以整除分块, 对与每一块需要求出那一块的\\(f\\)的和;单点修改区间求和树状数组可以维护;

时间复杂度$O(q\\sqrtl\\log l+ l \\log l) $

可以撒花了

然后这个柿子的理解

\\(\\sum\\limits_i=1^x\\sum\\limits_d|i1=\\sum\\limits_d=1^x\\lfloor\\fracxd\\rfloor\\)

1到x每一个数的所有约数的个数

就相当于枚举一个约数, 这个约数的倍数的个数, x以内d的倍数的个数就是\\(\\lfloor\\fracxd\\rfloor\\);

以上是关于10.2模拟赛总结的主要内容,如果未能解决你的问题,请参考以下文章

潍坊一中模拟赛10.2 妖精大作战

Xcode 10.2 无法在 iOS < 10 的模拟器上运行应用程序

无法在 iOS 模拟器 10.2 或 10.3 中切换软件键盘

csp-s模拟测试57(10.2)「天空龙」·「巨神兵」·「太阳神」

csp-s模拟测试56(10.2)Merchant「二分」·Equation「树状数组」

QNX Hypervisor 2.2用户手册]10.2 vdev 8259