列表

详情


NC245538. 胖头鱼头胖

描述

Z特别喜欢吃胖头鱼!所以他经常在家附近的鱼市买鱼,碰巧这个鱼市里面卖的都是胖头鱼。鱼市里有 n 家店铺,编号为,第 i 家店铺的鱼的库存量为 a_i ,即在第 i 家店铺中小Z可以选择购买 条鱼(买0条即是不买)
定义小Z的快乐值为在所有店铺买的鱼的数量的异或和,也就是说如果小Z在第 i 个店铺购买了 b_i 条鱼, 那么他的快乐值就等于  ,即,其中表示按位异或运算。
有一天,他去鱼市时突然想到了一个问题:如果只在编号为的这一段店铺区间中买鱼,有多少购买方法使得自己的快乐值为 s ?这个问题很难回答…… 因为小Z数学不好。于是,他只好求助聪明的你,来解决这个问题,由于这个答案可能很大,故输出时对 取模。

输入描述

第一行两个正整数 ,表示分别店铺个数以及询问次数。
第二行 n 个正整数 ,第i个整数表示第 i 家店铺中的鱼的库存量。

后面 q 行,每行三个整数 , 分别代表询问的一段店铺区间以及快乐值。

输出描述

输出 q 行,每行一个整数,依次表示询问对应的答案,答案对  取模。

示例1

输入:

6 6
1 1 4 5 1 4
1 1 0
1 2 0
1 3 0
1 4 0
1 5 0
1 6 0

输出:

1
2
4
20
40
168

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 1588ms, 内存消耗: 100136K, 提交时间: 2022-11-04 20:49:08

#include<bits/stdc++.h>
using namespace std;
#define fr(i,a,b) for(int i=a;i<=b;i++)
#define until(F) while(!(F))
#define ll long long
#define mod 1000000007
#define N 1024
#define M 10
#define invN 71289063
int n,Q,a[N];
int bl[N],pos[N],k;
struct FF{
	ll f[N];
	void FWT(){
		fr(j,0,M-1){
			fr(i,0,N-1){
				if(i>>j&1){
					ll x=f[i^(1<<j)],y=f[i];
					f[i^(1<<j)]=(x+y)%mod;
					f[i]=(x+mod-y)%mod;
				}
			}
		}
	}
}b[N],tmp[105],S1[105][M][M],S2[105][105];
FF mul(FF A,FF B){
	FF C;
	fr(i,0,N-1)C.f[i]=A.f[i]*B.f[i]%mod;
	return C;
}
void build(){
	for(int l=1,r;l<=n;l=r+1){
		r=min(n,l+M-1);
		pos[++k]=l;
		fr(i,l,r){
			bl[i]=k;
			S1[k][i-l][i-l]=b[i];
			fr(j,i+1,r){
				S1[k][i-l][j-l]=mul(S1[k][i-l][j-l-1],b[j]);
			}
		}
	}
//	printf("orz:%d\n",k);
	pos[k+1]=n+1;
	fr(i,1,k)tmp[i]=S1[i][0][pos[i+1]-pos[i]-1];
	fr(i,1,k){
		S2[i][i]=tmp[i];
		fr(j,i+1,k)S2[i][j]=mul(S2[i][j-1],tmp[j]);
	}
}
void query(int l,int r,int s){
	int pl=bl[l],pr=bl[r];
	FF res;
	if(pl==pr){
		res=S1[pl][l-pos[pl]][r-pos[pl]];
	}
	else{
		res=mul(S1[pl][l-pos[pl]][pos[pl+1]-pos[pl]-1],S1[pr][0][r-pos[pr]]);
		if(pl<pr-1)res=mul(res,S2[pl+1][pr-1]);
	}
	ll ans=0;
	fr(i,0,N-1){
		if(__builtin_popcount(i&s)&1)ans-=res.f[i];
		else ans+=res.f[i];
	}
	ans=(ans%mod+mod)%mod;
	printf("%lld\n",ans*invN%mod);
}
int main(){
//	return system("fc my.out .out"),0;
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	scanf("%d%d",&n,&Q);
	fr(i,1,n)scanf("%d",&a[i]);
	fr(i,1,n){
		fr(j,0,a[i])b[i].f[j]=1;
		b[i].FWT();
	}
	build();
//	FF res=S1[2][0][1];
//	res.FWT();
//	fr(i,0,15)printf("%lld ",res.f[i]*invN%mod);puts("");
	while(Q--){
		int l,r,s;
		scanf("%d%d%d",&l,&r,&s);
		query(l,r,s); 
	}
	return 0;
}

C++(clang++ 11.0.1) 解法, 执行用时: 1631ms, 内存消耗: 27052K, 提交时间: 2022-11-05 10:50:37

#include<iostream>
#include<vector>
using namespace std;

#define int long long
const int N=1055,mod=1e9+7;

int n,q;
int a[N][N];
pair<int,int> f[N][N];

int ksm(int a,int b)
{
    int ans=1;
    while(b)
    {
        if(b&1) ans=ans*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return ans;
}

void XOR(int *a,int n,int x)
{
    for(int o=2,k=1;o<=n;o<<=1,k<<=1)
    {
        for(int i=0;i<n;i+=o) 
         for(int j=0;j<k;j++)
          {
              int x=a[i+j],y=a[i+j+k];
              a[i+j]=(x+y)%mod;
              a[i+j+k]=(x-y+mod)%mod;
          }
    }
}

int calc(int l,int r,int i)
{
    if(f[r][i].second>f[l-1][i].second) return 0;
    return f[r][i].first*ksm(f[l-1][i].first,mod-2)%mod;
}

signed main()
{
    cin>>n>>q;
    for(int i=0;i<1024;i++) f[0][i]={1,0};
    for(int i=1,j;i<=n;i++) 
    {
        cin>>j;
        for(int s=0;s<=j;s++) a[i][s]=1;
        XOR(a[i],1024,1);
        for(int s=0;s<1024;s++) 
        {
            f[i][s]=f[i-1][s];
            if(a[i][s]==0) f[i][s].second++;
            else f[i][s].first=(f[i][s].first*a[i][s])%mod;
        }
    }
    int d=ksm(1024,mod-2);
    while(q--)
    {
        int l,r,s;
        cin>>l>>r>>s;
        int ans=0;
        for(int i=0;i<1024;i++) 
        {
            if(__builtin_popcount(i&s)&1) ans=(ans-calc(l,r,i)+mod)%mod;
            else ans=(ans+calc(l,r,i))%mod;
        }
        cout<<ans*d%mod<<'\n';
    }
    return 0;
}

上一题