L .Nice Trick(逆元)

L .Nice Trick

题意:给你一个s3表达式并且s3已经有具体计算公式,让你求一个s4(就 是 s3*a[i] (k<i<=n) ) )%1e9+7

题解:输入的时候处理s3表达式中的 :a[i]的前缀和 ; a[i]平方的前缀和 ; a[i]3次方的前缀和 。
这样s3可以在O(1)时间内求出。 计算s3的时候有除法的模,不能直接模除,因为1e9+7为质数利用费马小定理计算逆元, 然后遍历a[i] (3<i<=n) ,最后式子用sum统计 a[i]*solve(i-1) 就是结果。

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int mod=1e9+7;
ll ans1[maxn],ans2[maxn],ans3[maxn],a[maxn];
ll quick_mul(ll a,ll b)
{
	ll temp=a%mod,ans=1;
	while(b)
	{
		if(b&1)
			ans=(ans*temp)%mod;
		temp=(temp*temp)%mod;
		b>>=1;
	}
	return ans%mod;
}
ll ni(ll a,ll b)
{
	return  quick_mul(a,b-2)%mod;
}
ll solve(ll x){
	ll s1=((ans1[x]*ans1[x])%mod*ans1[x])%mod;
	ll s2=((3*ans2[x])%mod*ans1[x])%mod;
	ll s3=((2*ans3[x])%mod);
	ll s4=s1-s2+s3;
	return s4*ni(6,mod)%mod;
}
int main()
{
	ll n;
	while(cin>>n)
	{
		ans1[0]=0,ans2[0]=0,ans3[0]=0;
		for(int i=1;i<=n;i++)
		{
			cin>>a[i];	
			ans1[i]=(ans1[i-1]+a[i])%mod;
			ans2[i]=(ans2[i-1]+(a[i]*a[i])%mod)%mod;
			ans3[i]=(ans3[i-1]+((a[i]*a[i])%mod*a[i])%mod)%mod;	
		}
		ll sum=0;
		for(int i=4;i<=n;i++)
		{
			sum+=(a[i]*solve(i-1))%mod;
		}
		cout<<((sum)%mod)<<endl;
	}
	return 0;
}
发布了88 篇原创文章 · 获赞 30 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43667611/article/details/102211271
l