zoukankan      html  css  js  c++  java
  • Subsequence Sum Queries

    Problem

    有一个长度为(n)的数列,一个数(m)(q)个询问,每次询问区间([l_i, r_i])中有多少子序列的和是(m)的倍数。

    Solution

    分治,将询问分配到各个区间。若一个区间的左区间完全包含某个询问的询问区间,则将该询问分配给该区间的左区间去处理,反之亦然。若某个询问的询问区间跨立于该区间的左右两个区间之间,则在该区间进行处理。

    Code

    /*
     Author: LargeDumpling
     Email: LargeDumpling@qq.com
     Edit History:
    	2018-07-24	File created.
    */
    
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<vector>
    #include<algorithm>
    using namespace std;
    const int MAXN=200050;
    const int mod=1000000007;
    struct jz
    {
    	int l,r;
    	long long ans;
    	jz() { l=r=ans=0; }
    }Q[MAXN];
    int n,m,qn,a[MAXN];
    long long f[MAXN][20];
    void read1n(int &x)
    {
    	char ch;
    	for(ch=getchar();ch<'0'||'9'<ch;ch=getchar());
    	for(x=0;'0'<=ch&&ch<='9';ch=getchar())
    		x=(x<<1)+(x<<3)+ch-'0';
    	return;
    }
    void calc(int l,int r,vector<int> &q)
    {
    	if(l==r)
    	{
    		int cnt=1;
    		if(a[l]%m==0) cnt++;
    		for(unsigned i=0;i<q.size();i++)
    			Q[q[i]].ans=cnt;
    		return;
    	}
    	int mid=(l+r)>>1;
    	vector<int> qn[2];
    	/*for(int i=l;i<=r;i++)
    	{
    		memset(f[i],0,sizeof(f[i]));
    		f[i][0]++;
    		f[i][a[i]%m]++;
    	}
    	for(int i=mid-1;l<=i;i--)
    	{
    		long long tem[20];
    		memset(tem,0,sizeof(tem));
    		for(int j=0;j<m;j++) // This is not necessary, j is useful only when j==0 or j==a[i]
    			for(int k=0;k<m;k++)
    				tem[(j+k)%m]=(tem[(j+k)%m]+f[i][j]*f[i+1][k]%mod)%mod;
    		memcpy(f[i],tem,sizeof(tem));
    	}
    	for(int i=mid+2;i<=r;i++)
    	{
    		long long tem[20];
    		memset(tem,0,sizeof(tem));
    		for(int j=0;j<m;j++)
    			for(int k=0;k<m;k++)
    				tem[(j+k)%m]=(tem[(j+k)%m]+f[i][j]*f[i-1][k]%mod)%mod;
    		memcpy(f[i],tem,sizeof(tem));
    	}*/
    	memset(f[mid],0,sizeof(f[mid]));
    	f[mid][0]++; f[mid][a[mid]%m]++;
    	memset(f[mid+1],0,sizeof(f[mid+1]));
    	f[mid+1][0]++; f[mid+1][a[mid+1]%m]++;
    	long long tem[20];
    	for(int i=mid-1;l<=i;i--)
    	{
    		memset(tem,0,sizeof(tem));
    		for(int j=0;j<m;j++)
    		{
    			tem[j]=(tem[j]+f[i+1][j])%mod;
    			tem[(j+a[i])%m]=(tem[(j+a[i])%m]+f[i+1][j])%mod;
    		}
    		memcpy(f[i],tem,sizeof(tem));
    	}
    	for(int i=mid+2;i<=r;i++)
    	{
    		memset(tem,0,sizeof(tem));
    		for(int j=0;j<m;j++)
    		{
    			tem[j]=(tem[j]+f[i-1][j])%mod;
    			tem[(j+a[i])%m]=(tem[(j+a[i])%m]+f[i-1][j])%mod;
    		}
    		memcpy(f[i],tem,sizeof(tem));
    	}
    	for(unsigned i=0;i<q.size();i++)
    	{
    		if(Q[q[i]].r<=mid) qn[0].push_back(q[i]);
    		if(mid<Q[q[i]].l) qn[1].push_back(q[i]);
    		if(Q[q[i]].l<=mid&&mid<Q[q[i]].r)
    		{
    			for(int j=0;j<m;j++)
    				Q[q[i]].ans=(Q[q[i]].ans+f[Q[q[i]].l][j]*f[Q[q[i]].r][(m-j)%m])%mod;
    		}
    	}
    	if(qn[0].size()) calc(l,mid,qn[0]);
    	if(qn[1].size()) calc(mid+1,r,qn[1]);
    	return;
    }
    int main()
    {
    	read1n(n); read1n(m);
    	for(int i=1;i<=n;i++)
    		read1n(a[i]);
    	read1n(qn);
    	vector<int> q;
    	for(int i=1;i<=qn;i++)
    	{
    		read1n(Q[i].l);
    		read1n(Q[i].r);
    		q.push_back(i);
    	}
    	calc(1,n,q);
    	for(int i=1;i<=qn;i++)
    		printf("%lld
    ",Q[i].ans);
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
    
  • 相关阅读:
    怎么防止重复提交
    JSP三大指令是什么?
    python中字符串的编码和解码
    什么是 JavaConfig?
    Spring Boot 有哪些优点?
    如何重新加载 Spring Boot 上的更改,而无需重新启动服务器?
    Mybatis 动态 sql 是做什么的?都有哪些动态 sql?能简述一下动态 sql 的执行原理不?
    如果你也用过 struts2.简单介绍下 springMVC 和 struts2 的区别有哪些?
    学习笔记——命令模式Command
    学习笔记——中介者模式Mediator
  • 原文地址:https://www.cnblogs.com/LargeDumpling/p/9369144.html
Copyright © 2011-2022 走看看