ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2022.8.12 颓废记录

2022-08-13 00:34:33  阅读:161  来源: 互联网

标签:le 颓废 int ll 12 maxn 2022.8 ans sum


Preface

不想开学 QAQ。

Content

[CF1252K]Addition Robot

挺新鲜的一道题,题解

[CF665E]Beautiful Subarrays

给定 \(a_{1\sim n}\),求满足 \(\bigoplus\limits_{i=l}^{r} a_i \ge k\) 的 \([l,r]\) 的数量。

\(1\le n\le 10^6,1\le a_i,k\le 10^9\)。

一眼题,把前缀和扔字典树里计算即可。时间复杂度 \(O(n\log k)\)。

Code

// Problem: CF665E Beautiful Subarrays
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/CF665E
// Memory Limit: 500 MB
// Time Limit: 3000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 5;
const int maxk = 30;
int trie[maxn * maxk][2],sum[maxn * maxk],rt,sz,n,k,cur;
void insert(int x) {
    int u = rt;
    ++ sum[u];
    for(int i = 29;~ i;-- i) {
        int c = x >> i & 1;
        if(!trie[u][c])trie[u][c] = ++ sz;
        ++ sum[u = trie[u][c]];
    }
    return ;
}
int query(int x) {
    int ans = 0,u = rt,p = 0;
    for(int i = 29;~ i;-- i) {
        if(!u)break ;
        int c = x >> i & 1;
        if(k >> i & 1) {
            u = trie[u][c ^ 1];
        }
        else {
            ans += sum[trie[u][c ^ 1]];
            u = trie[u][c];
        }
    }
    return ans + sum[u];//equal
}
int main() {
    rt = ++ sz;
    scanf("%d %d",&n,&k);
    insert(cur);
    long long cnt = 0;
    for(int i = 1,x;i <= n;++ i) {
        scanf("%d",&x);
        cur ^= x;
        cnt += query(cur);
        insert(cur);
    }
    printf("%lld\n",cnt);
    return 0;
}

[CF103D]Time to Raid Cowavans

给定 \(a_{1\sim n}\),\(m\) 次询问,每次求出 \(a_{t}+a_{t+k}+a_{t+2k}+\ldots a_{t+pk}(t+(p+1)k\gt n)\)。

\(1\le n,m \le 3\times 10^5,1\le a_i\le 10^9,1\le t,k\le n\)。

不难发现这是一道根号分治题,但原题 \(68\rm{MB}\) 的空间很让人头疼。

哈希冲突这道题中,由于是全局询问,所以空间没有问题。

但现在引入了 \(t\),就需要 \(O(n\sqrt{n})\) 的空间,肯定过不了。

由于这题不需要修改,考虑离线,按 \(t\) 升序排序。

我本来想用 std::unordered_map 存一下跑记忆化搜索,这样理论上是 \(O(n\log n)\) 的空间,但还是过不了。

实际上,将 \(t\) 升序排序后,若 \(k\le \sqrt{n}\),那么我们用一个变量 \(p\) 删去 \(1\sim t-1\) 对答案的贡献就能直接计算出正确的结果。

时间复杂度:\(O(n\sqrt{n})\),空间复杂度 \(O(n)\)。

Code

// Problem: CF103D Time to Raid Cowavans
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/CF103D
// Memory Limit: 68 MB
// Time Limit: 4000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5 + 5;
const int maxm = 550;
typedef long long ll;
int n,a[maxn],m;
struct node {
    int t,k,id;
    node() {
        t = k = id = 0;
    }
}Q[maxn];
ll s[maxm][maxm];
ll ans[maxn];
int main() {
    scanf("%d",&n);
    int t = sqrt(n);
    for(int i = 1;i <= n;++ i) {
        scanf("%d",&a[i]);
        for(int j = 1;j <= t;++ j)s[j][i % j] += a[i];
    }
    scanf("%d",&m);
    for(int i = 1;i <= m;++ i) {
        scanf("%d %d",&Q[i].t,&Q[i].k);
        Q[i].id = i;
    }
    sort(Q + 1 , Q + 1 + m , [&](const node& p,const node& q) {
        return p.t < q.t;
    });
    int p = 1;
    for(int i = 1;i <= m;++ i) {
        if(Q[i].k <= t) {
            for(;p < Q[i].t;++ p)
                for(int j = 1;j <= t;++ j)s[j][p % j] -= a[p];
            ans[Q[i].id] = s[Q[i].k][Q[i].t % Q[i].k];
        }
        else {
            for(int j = Q[i].t;j <= n;j += Q[i].k)ans[Q[i].id] += a[j];
        }
    }
    for(int i = 1;i <= m;++ i)printf("%lld\n",ans[i]);
    return 0;
}

后面 vp 了一场 ABC,结果 E 题简单 BFS 打崩了,心态爆炸 QAQ。

[ABC246F]typewriter

\(n\) 个字符串 \(s_{1\sim n}\),每个字符串都是 \(\texttt{abcd\ldots z}\) 的子序列。

你可以选择其中一个字符串 \(s_i\),用 \(s_i\) 中的字符组成一个长为 \(L\) 的字符串。

求可以组成的字符串的数量。

\(1\le n\le 18,1\le L\le 10^9\)。

看到 \(L\) 的范围我下意识地去想矩阵快速幂优化 DP,结果搞不出来,因为重复的数量实在不好维护。

看了题解后,我恍然大悟:\(n\) 这么小的范围,有重复,联想到什么?

没错,容斥原理。

如果若干个字符串有 \(cnt\) 个重复的字符,那么它们间重复字符串的数量即为 \(cnt^L\)。

原因不难理解,想要重复,必然是 \(1\sim L\) 每个字符都是这 \(cnt\) 个字符中的某个。

想明白了这个,很容易写出代码。

时间复杂度:\(O(2^n(n+\log L))\)。

Code

// Problem: F - typewriter
// Contest: AtCoder - AtCoder Beginner Contest 246
// URL: https://atcoder.jp/contests/abc246/tasks/abc246_f
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
using namespace std;
const int maxn = 20;
typedef long long ll;
const ll mod = 998244353;
ll m;
char s[maxn][30];
int n,sum[maxn],len[maxn];
ll power(ll x,ll y) {
    ll ans = 1;
    for(;y;y >>= 1) {
        if(y & 1)(ans *= x) %= mod;
        (x *= x) %= mod;
    }
    return ans;
}
int popcount(int x) {
    int ans = 0;
    for(;x;x -= x & -x)++ ans;
    return ans;
}
int main() {
    scanf("%d %lld",&n,&m);
    ll ans = 0;
    for(int i = 1;i <= n;++ i) {
        scanf("%s",s[i] + 1);
        len[i] = strlen(s[i] + 1);
        for(int j = 1;j <= len[i];++ j)sum[i] |= 1 << (s[i][j] - 'a');
    }
    //这里我一开始很疑惑:交集不是等于全集减去补集的并集吗,为啥不用提前算全集
    //后来想明白了,k 的二进制位只有一位时其实就计算上了全集的贡献
    for(int k = 1;k < (1 << n);++ k) {
        int popcnt = 0,cur = (1 << 26) - 1;
        for(int i = 1;i <= n;++ i) {
            if(!(k >> (i - 1) & 1))continue ;
            ++ popcnt;
            cur &= sum[i];
        }
        (ans += ((popcnt & 1) ? 1ll : -1ll) * power(popcount(cur) , m) % mod + mod) %= mod;
    }
    printf("%lld",ans);
    return 0;
}

标签:le,颓废,int,ll,12,maxn,2022.8,ans,sum
来源: https://www.cnblogs.com/Royaka/p/16581775.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有