后三个点RE,找不到错因
查看原帖
后三个点RE,找不到错因
230808
Zxsoul楼主2021/5/12 15:29

后三个点RE

/*
5/8 20:00 开始敲 
5/8 20:36 有数了 15 16 16 
5/8 20:40 7 8 8
5/8 20:49 5 6 6 过样例啦 然后 0 分 
5/12 15:18 40分啦 num[a[i]]-->num[i] 
5/12 15:23 70分 (1<<num[a[i])num[a[i]]太大,位运算干不了,可以用数组取摸,后三个点RE 
*/ 
#include <map> 
#include <cmath>
#include <queue>
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#define int long long
using namespace std;

const int A = 1e7+10;
const int B = 1e7+10;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;

inline int read() {
  char c = getchar();
  int x = 0, f = 1;
  for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
  for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
  return x * f;
}
int js;//记录删除后的书 
map<int,int>lsh;//离散化用 
int pre[B],cnt;//处理因子 
int num[B];//记录相同的重量出现的个数 
int n,p,f[5000][5000],a[B],t;
int gcd(int x,int y) {return y==0 ? x : gcd(y,x%y);}

void prepare()//知道因子 
{
	for (int i=1;i*i<=p;i++)
	{
		if (p%i==0) 
		{
			pre[++cnt]=i;
			if (i*i==p) continue;
			pre[++cnt]=p/i;
		}
	}
	sort(pre+1,pre+cnt+1);
	for (int i=1;i<=cnt;i++)
	{
		lsh[pre[i]]=i;
	}
} 

int pow2[B];
main()
{
	n=read(); t=read(); p=read();
	pow2[0]=1;
	for (int i=1;i<=10000;i++)
		pow2[i]=pow2[i-1]*2%mod;
	for (int i=1;i<=n;i++)
	{
		int x=read();
		int s=gcd(x,p);
		if (!num[s]) a[++js]=s;//保证没有重复的数了 
		num[s]++;//计数用 
	}
	prepare();//处理因子 	 
	for (int i=1;i<=js;i++) 
		for (int j=1;j<=cnt;j++)
		{
			(f[i][lsh[pre[j]]]+=f[i-1][lsh[pre[j]]])%=mod;//选 
			if (pre[j]==a[i]) f[i][lsh[pre[j]]]+=(pow2[num[a[i]]]%mod-1)%mod;
			int k=lsh[gcd(pre[j],a[i])];
			(f[i][k]+=1ll*f[i-1][j]*((pow2[num[a[i]]])-1)%mod)%=mod;
			f[i][lsh[pre[j]]]%=mod;
			f[i][k]%=mod;
		}
		
	while (t--)
	{
		int w=read();
		int ans=0;
		for (int i=1;i<=cnt;i++)
		{
			if (w%pre[i]==0) 
				(ans+=f[js][lsh[pre[i]]])%=mod;
		}
		printf("%lld\n",ans%mod);
	}
}
2021/5/12 15:29
加载中...