汕头网站建设推广价格南通企业网页制作
web/
2025/10/4 17:58:52/
文章来源:
汕头网站建设推广价格,南通企业网页制作,国内做外贸的网站,怎么做网站动态地图题目
这里写链接内容
题意
给出一个最长为200000200000数列 给出一堆最多为200000200000个询问区间#xff0c;问从这些区间中取出一些数使得数字之和是m的倍数#xff0c;有多少种方案。其中保证1≤m≤201≤m≤20。
题解
最容易想到的方法就是倍增dp来做。 定义f[i][…题目
这里写链接内容
题意
给出一个最长为200000200000200000数列 给出一堆最多为200000200000200000个询问区间问从这些区间中取出一些数使得数字之和是m的倍数有多少种方案。其中保证1≤m≤201≤m≤201≤m≤20。
题解
最容易想到的方法就是倍增dp来做。 定义f[i][j][k]f[i][j][k]f[i][j][k]表示区间[l,l2j)[l,l2j)[l,l+2^j)内选取数字之和modmkmodmkmod m == k的方案数。 这种dpdpdp很容易想到转移方程也比较容易写但是空间复杂度会爆炸掉因此我们必须换一种方法。
离线分治算法 对于最开始的区间[1,n][1,n][1,n]我们考虑它的中点mid(1n)/2mid(1n)/2mid = (1+n)/2有的询问区间包含了mid这个点有的在mid点左边有的在mid点右面。 在这里我们可以用O(n)O(n)O(n)的时间复杂度内计算出所有包含mid点的询问区间的答案然后把剩下的询问区间分到左右两边然后再分治解决。
如何在O(n)O(n)O(n)的时间复杂度内计算出所有包含mid点的询问区间的答案 记录f[i][k]f[i][k]f[i][k]表示区间[l,mid][l,mid][l,mid]之间选取数字之和模m等于k的方案数。 记录g[i][k]g[i][k]g[i][k]表示区间[mid1,i][mid1,i][mid+1,i]之间选取数字之和模m等于k的方案数。 那么询问区间[l,r](l≤mid≤r)的答案就是∑m−10f[l][i]∗g[r][(m−i)%m]询问区间[l,r](l≤mid≤r)的答案就是∑0m−1f[l][i]∗g[r][(m−i)%m]询问区间[l,r] (l≤mid≤r) 的答案就是:\sum_{0}^{m-1}f[l][i]*g[r][(m-i)\%m]
代码
#include iostream
#include cstdio
#include algorithm
#include vector
#include cstring
using namespace std;
#define pr(x) cout#x:xendl
const int maxn 2e57;
int n,m,q;
int query[maxn][3];
int g[maxn][22];
int f[maxn][22];
int a[maxn];
const int mod 1e97;
void solve(int l,int r,vectorint qs){if(l r || qs.size() 0)return ;int mid (l r) / 2;for(int i l;i r;i) for(int j 0;j m;j)g[i][j] f[i][j] 0;f[mid][0] 1;for(int i mid-1;i l;i--){for(int j 0;j m;j){f[i][(ja[i])%m] (f[i][(ja[i])%m] (long long)f[i1][j]) % mod;f[i][j] (f[i][j] f[i1][j]) % mod;}}g[mid-1][0] 1;for(int i mid;i r;i){for(int j 0;j m;j){g[i][j] (g[i][j] g[i-1][j]) % mod;g[i][(ja[i])%m] (g[i][(ja[i])%m] (long long)g[i-1][j]) % mod;}}vectorint qs1,qs2;for(auto i : qs){if(query[i][1] mid-1) qs1.push_back(i);else if(query[i][0] mid) qs2.push_back(i);else {if(query[i][1] mid-1){query[i][2] f[query[i][0]][0];}else if(query[i][0] mid){query[i][2] g[query[i][1]][0];}else{for(int j 0;j m;j){query[i][2] (query[i][2] (long long)f[query[i][0]][j] * g[query[i][1]][(m-j)%m])% mod;}}} }solve(l,mid,qs1);solve(mid,r,qs2);
}
int main(){scanf(%d%d,n,m);for(int i 1;i n;i){scanf(%d,a[i]);a[i] % m;}vectorint qs;scanf(%d,q);for(int i 0; i q;i){scanf(%d %d,query[i][0],query[i][1]);qs.push_back(i);}solve(1,n1,qs);for(int i 0;i q;i){printf(%d\n,query[i][2]);}return 0;
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/86907.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!