P10886 【MX-S3-T2】「FeOI Round 1」Journey 题解

我们肯定是要先求出来一个位置被加的次数,然后和权值乘一下就行。

对于一个位置 i,右端点 b 肯定是随便选,一共 ni+1 种情况。再是对于每一种步长 c,左端点 a 都有 ic 种取值,暴力计算,时间复杂度 O(n2)。(提交记录

考虑如何优化,对于第 i 个位置,设 si=c=1nic,那对于一个 c,如果 ic>i1c,那么 i1 一定是 c 的倍数。所以,i1 有几个因数,si 就会变大多少,即 si=si1+di1。直接欧拉筛即可。

代码
#include<bits/stdc++.h>
using namespace std;
inline void rd(){}
template<typename T,typename ...U>
inline void rd(T &x,U &...args){
	char ch=getchar();
	T f=1;x=0;
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	x*=f;rd(args...);
}
const int N=2e7+5,mod=1e9+7;
int n,a,b,c,gn;
int t[N],ans;
int pri[N],cnt,d[N],num[N];
bool vis[N];
inline void Euler(){
	d[1]=num[1]=1;
	for(int i=2;i<=n;i++){
		if(!vis[i]){
			pri[++cnt]=i;
			d[i]=2,num[i]=1;
		}
		for(int j=1;j<=cnt&&pri[j]*i<=n;j++){
			vis[pri[j]*i]=1;
			if(i%pri[j]==0){
				num[i*pri[j]]=num[i]+1;
				d[i*pri[j]]=d[i]/num[i*pri[j]]*(num[i*pri[j]]+1);
				break;
			}
			num[i*pri[j]]=1;
			d[i*pri[j]]=d[i]*2;
		}
	}
}
signed main(){
	rd(n,a,b,c,gn);
	t[1]=n;Euler();
	for(int i=2;i<=n;i++)t[i]=t[i-1]+d[i-1];
	ans=1ll*gn*t[n]%mod;
	for(int i=n-1;i>=1;i--){
		gn=(1ll*a*gn%mod*gn%mod+1ll*b*gn%mod+c)%mod;
		(ans+=1ll*gn*t[i]%mod*(n-i+1)%mod)%=mod;
	}printf("%d\n",ans);
	return 0;
}

本文作者:KIreteria

本文链接:https://www.cnblogs.com/11-twentythree/p/18364899

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   KIreteria  阅读(38)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起