拉格朗日插值法

本文介绍了一种计算K维空间中与原点切比雪夫距离不超过N的所有点与原点的距离之和的方法。通过组合数学与数论技巧,实现了高效的计算方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题面:

统计K维空间中与原点切比雪夫距离不超过N的点与原点的切比雪夫距离和


solution:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<bitset>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;

const int maxn = 1E6 + 10;
typedef long long LL;
const LL mo = 1000000007;

int T,N,K,tot,pri[maxn*2];
bool not_pri[maxn*2];
LL Ans,F[maxn],fac[maxn],_fac[maxn],pre[maxn],suf[maxn],mi[maxn*2];

int Mul(const LL &x,const LL &y) {return x * y % mo;}
int Add(const int &x,const int &y) {return (x + y) % mo;}
int Dec(const int &x,const int &y) {return (x - y + mo) % mo;}

int ksm(int x,int y)
{
	int ret = 1;
	for (; y; y >>= 1)
	{
		if (y & 1) ret = Mul(ret,x);
		x = Mul(x,x);
	}
	return ret;
}

int main()
{
	#ifdef DMC
		freopen("DMC.txt","r",stdin);
	#else
		freopen("distance.in","r",stdin);
		freopen("distance.out","w",stdout);
	#endif
	
	cin >> T; fac[0] = _fac[0] = 1;
	for (int i = 1; i < maxn; i++)
		fac[i] = Mul(fac[i-1],i),_fac[i] = Mul(_fac[i-1],Dec(0,i));
	fac[maxn-1] = ksm(fac[maxn-1],mo - 2);
	for (int i = maxn - 2; i >= 0; i--)
		fac[i] = Mul(fac[i+1],i + 1);
	_fac[maxn-1] = ksm(_fac[maxn-1],mo - 2);
	for (int i = maxn - 2; i >= 0; i--)
		_fac[i] = Mul(_fac[i+1],Dec(0,i + 1));
	
	while (T--)
	{
		cin >> K >> N; int G = 2*(K+2) + 1; mi[1] = 1;
		for (int i = 2; i <= G; i++)
		{
			if (!not_pri[i])
			{
				pri[++tot] = i;
				mi[i] = ksm(i,K);
			}
			for (int j = 1; j <= tot; j++)
			{
				LL Nex = 1LL*pri[j]*i;
				if (Nex > G) break;
				not_pri[Nex] = 1;
				mi[Nex] = Mul(mi[i],mi[pri[j]]);
				if (i % pri[j] == 0) break;
			}
		}
		for (int i = 2; i <= G; i++) not_pri[i] = 0; tot = 0;
		for (int i = 1; i <= K + 2; i++)
			F[i] = Add(F[i-1],Mul(i,Dec(mi[2*i + 1],mi[2*i - 1])));
		Ans = 0; pre[0] = suf[K+3] = 1;
		for (int i = 1; i <= K + 2; i++)
			pre[i] = Mul(pre[i-1],Dec(N,i));
		for (int i = K + 2; i >= 0; i--)
			suf[i] = Mul(suf[i+1],Dec(N,i));
		for (int i = 1; i <= K + 2; i++)
		{
			LL A = Mul(pre[i - 1],suf[i + 1]);
			LL B = Mul(fac[i - 1],_fac[K + 2 - i]);
			Ans = Add(Ans,Mul(Mul(A,B),F[i]));
		}
		cout << Ans << endl;
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值