H.Hamster's Sequence(2019武大校赛现场赛)(莫队or前缀和+离线处理)(吉比特杯第二届湖北省程序设计大赛) 解题报告 Apare_xzc

H.Hamster’s Sequence(2019武大校赛现场赛)(莫队/前缀和+离线处理)(吉比特杯第二届湖北省程序设计大赛) 解题报告

xzc 2019/4/18

CCNU_你们好强啊我们都是面包手


题意:
  给出n个整数a1,a2…an ,和m个询问,每次询问从[L,R]这个区间所有数的乘积的因数的个数 (求a[L]*a[L+1]*a[L+2]*…*a[R-1]*a[R] 的因数的个数)


input:

5 5
1 2 3 4 5
1 1
2 2 
3 3 
1 5
4 5

output:

1
2
2
16
6

分析:
  一个数因数的个数是所有质因子出现的个数+1后的乘积
  剩下的上题解:

  • 首先,我们得看出来这道题是个简单题。
  • 至于那个合数mod,实际上是唬人的,你一些数乘起来对合数取模可以直接取
  • 然后我们根据题目描述我们知道,说ai在2147483647以内,但由ai=rand()*rand()得出,实际上ai的质因子最大的不会超过32767(rand()在c++中的随机数据范围在0到 32767)
  • 我们知道一个因数的个数和这个数的质因数的个数有关
A=a1^n1*a2^n2*a3^n3…an^nn因数的个数等于
(1+n1) * (1+n2) * (1+n3) * … * (1+nn)
  • 然后计算答案:
    planA: 直接莫队
    planB:对于32767中的质数分别统计对答案的贡献,用前缀和计算即可

先上我的AC代码

/* Author: CCNU XuZhichao state: AC 2019/4/17 22:40 1105 */
#include <bits/stdc++.h>
#define For(i,a,b) for(register int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
#define Mst(a,b) memset(a,(b),sizeof(a))
#define LL long long
#define MP make_pair
#define pb push_back
using namespace std;
const int maxn = 1e5+20;
const int N = 32767;  //3512个素数
const int mod = 35808247;
int cntOfPrime,sushu[N],n,m;
bool notPrime[N+20];
int mp[N+20];
void getPrime(int &cnt)
{
	cnt = 0;
	For(i,2,N)
	{
		if(!notPrime[i]) mp[i] = cnt, sushu[cnt++] = i;
		for(int j=0;j<cnt&&1ll*i*sushu[j]<=N;++j)
		{
			notPrime[i*sushu[j]] = true;
			if(i%sushu[j]==0) break;
		}
	}
}
pair<int,int> ask[maxn]; 
int a[maxn];
LL ans[maxn];
int sum[maxn];
void f(int i)
{
	int p = sushu[i];
	sum[0] = 0;
	For(i,1,n)
	{
		int x = a[i];
		int cnt = 0;
		while(x%p==0) ++cnt,x/=p;
		sum[i] = sum[i-1]+cnt;
	}
	For(i,1,m)
	{
		int nn = sum[ask[i].second]-sum[ask[i].first-1]+1;
		ans[i] = ans[i]*nn%mod;	
	}
}
int main()
{
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    getPrime(cntOfPrime);
    scanf("%d%d",&n,&m);
    For(i,1,n) scanf("%d",a+i), ans[i] = 1;
    For(i,1,m)
    {
    	scanf("%d%d",&ask[i].first,&ask[i].second);
	}
    For(i,0,3511)
    {
    	f(i);
	}
	For(i,1,m)
		printf("%lld\n",ans[i]);
    
    return 0;
}

这是第一发用vector压缩存储了所有因数前缀和的代码

跑了100多秒,输出都正确,100000(询问)*3512(个素数)*2*log2(100000)(两次二分)
/* Author: CCNU XuZhichao state: TLE 2019/4/17 22:09 1105 */
#include <bits/stdc++.h>
#define For(i,a,b) for(register int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
#define Mst(a,b) memset(a,(b),sizeof(a))
#define LL long long
#define MP make_pair
#define pb push_back
using namespace std;
const int maxn = 1e5+20;
const int N = 32767;  //3512个素数
const int mod = 35808247;
int cntOfPrime,sushu[N];
bool notPrime[N+20];
int mp[N+20];
void getPrime(int &cnt)
{
	cnt = 0;
	For(i,2,N)
	{
		if(!notPrime[i]) mp[i] = cnt, sushu[cnt++] = i;
		for(int j=0;j<cnt&&1ll*i*sushu[j]<=N;++j)
		{
			notPrime[i*sushu[j]] = true;
			if(i%sushu[j]==0) break;
		}
	}
}
int a[maxn];
vector<pair<int,int> > v[3512];
void f(int id)
{
	int x = a[id],p,t;
	for(int i=0;i<cntOfPrime&&sushu[i]<=x/sushu[i];++i)
	{
		p = sushu[i];
		if(x%p) continue;
		int cntt = 0;
		while(x%p==0) ++cntt,x/=p;
		t = mp[p]; //下标
		int sz = v[t].size();
		if(sz>1) cntt+=v[t][sz-1].second;
		v[t].pb(MP(id,cntt));
	}
	if(x>1)
	{
		t = mp[x];
		int cntt = 1;
		int sz = v[t].size();
		if(sz>1) cntt+=v[t][sz-1].second;
		v[t].pb(MP(id,cntt));
	}
}
int getNum(int L,int R,int i)
{
	int x1 = upper_bound(v[i].begin(),v[i].end(),MP(L,1000))-v[i].begin()-1;
	int x2 = upper_bound(v[i].begin(),v[i].end(),MP(R,1000))-v[i].begin()-1;
	return max(0,v[i][x2].second-v[i][x1].second) + 1;
}
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    getPrime(cntOfPrime);
    For(i,0,3511) v[i].push_back(MP(-2,0));
    int n,m,L,R;
    scanf("%d%d",&n,&m);
    For(i,1,n)
    	scanf("%d",a+i);
    For(i,1,n)
    	f(i); 
    //预处理前缀和0ms 
    while(m--)
    {
    	scanf("%d%d",&L,&R);
    	LL ans = 1;
    	For(i,0,3511) //100000个询问*3000*log(100000); 
    	{
    		ans  = ans * getNum(L-1,R,i)%mod;
		}
		printf("%lld\n",ans);
	}
    return 0;
}

附:武大出题人写的标程(莫队算法)

#include <bits/stdc++.h>
using namespace std;
const int M = 100100;
const long long MOD = 35808247;
//MOD=5981*5987
int n,m;
struct node
{
	int l,r,id;
}q[M];
long long ans[M];
vector<int>b[M];
int hash1[M],block[M];
int num[M],prime[M],len,flag[M];
void update(int x,int y)
{
	for(int i=0;i<b[x].size();i++)
		num[hash1[b[x][i]]]+=y;
}
long long get_ans()
{
	long long cnt=1;
	for(int i=1;i<=len;i++)
		if(num[i]!=0)
			cnt=cnt*(num[i]+1)%MOD;
	return cnt; 
}
bool cmp(const node &x,const node &y)
{
	if(block[x.l]==block[y.l])
		return x.r<y.r;
	return x.l<y.l;
}
void deal()
{
	int l=1,r=0;
	for(int i=1;i<=m;i++)
	{
		for(;r<q[i].r;r++)
			update(r+1,1);
		for(;r>q[i].r;r--)
			update(r,-1);
		for(;l<q[i].l;l++)
			update(l,-1);
		for(;l>q[i].l;l--)
			update(l-1,1);
		ans[q[i].id]=get_ans();
	}
}
void print()
{
	for(int i=1;i<=m;i++)
		printf("%I64d\n",ans[i]);
	printf("\n");
}
int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("stdout.txt","w",stdout); 
	for(int i=2;i<=40000;i++)
		if(!flag[i])
		{
			prime[++len]=i;
			for(int j=i*i;j<=40000;j+=i)
				flag[j]=1;
			hash1[i]=len;
		}
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		int x;
		scanf("%d",&x);
		for(int j=1;prime[j]*prime[j]<=x;j++)
			while(x%prime[j]==0)
			{
				b[i].push_back(prime[j]);
				x/=prime[j];
			}
		if(x!=1)
			b[i].push_back(x);
	}
	int block_num=300;
	for(int i=1;i<=n;i++)
		block[i]=(i/block_num)+(i%block_num==0);
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&q[i].l,&q[i].r);
		q[i].id=i;
	}
	sort(q+1,q+1+n,cmp);
	deal();
	print();
	return 0;
} 


2019/4/18 07:11
全部评论

相关推荐

昨天 12:44
已编辑
吉林大学 Java
是个千人厂,没听过名字。1.&nbsp;做一个自我介绍。2.&nbsp;你这个项目和技术栈从哪里学的?有报辅导班嘛[答&nbsp;都是是自己网上学的,学校教的东西没用]3.&nbsp;我看了你放在github上的项目,前端也是你写的嘛[答&nbsp;AI写的,90%精力用于后端开发,前端单纯用于作为后端逻辑的可视化技术验证(骗你的其实后端也是AI写的)]4.&nbsp;好,你觉得这些技术栈研究得最深刻的是哪个[答&nbsp;八股压根没背到后面,昨晚背了MySQL就说MySQL]5.&nbsp;那讲一下MySQL的索引[答&nbsp;从B+树选型一路吟唱到联合索引,索引失效]6.&nbsp;联合索引ABC问题,AB走索引嘛,BC走索引嘛?BAC走索引嘛?A&nbsp;or&nbsp;B&nbsp;走索引嘛[走,不走,走,不走。面试官点头说可以]7.&nbsp;讲一下项目里Redission分布式锁实现8.&nbsp;Watchdog机制具体是怎么工作9.&nbsp;消息队列有考虑过Kafka嘛,怎么选型的10.&nbsp;你这个项目消息队列可能出现什么问题,怎么解决这个问题?[瞎扯没用的,被面试官引导答了视频处理可能产生消息堆积问题,然后开始吟唱]11.&nbsp;文件分片自己写的还是用的什么框架?上传进度的Redis数据结构?上传的视频有多大?小分片大小?12.&nbsp;项目里Redis会话记忆是啥意思?[面试官说不行,没人把这个全放Redis里[生气R]]13.&nbsp;那这和直接查数据库有什么区别[扯了Token成本和解决幻觉问题之类的,给面试官听笑了,我最后也没绷住]14.&nbsp;你平时是怎么使用AI&nbsp;coding的15.&nbsp;算法,给了我一个leedcode链接,一看做过了。然后换了一道三数之和,也做过了。然后面试官说算了,让我讲讲思路吧反问:1.有什么需要提高的地方2.介绍一下部门业务有哪些这个面试官真的感官非常非常好,问问题还疯狂引导,感觉不会也会了。找实习&nbsp;&nbsp;牛客AI配图神器#
查看15道真题和解析
点赞 评论 收藏
分享
02-26 01:13
集美大学 Java
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务