【Coel.解题报告】【夏城插值!】【模板】拉格朗日插值
题前碎语
\(And\) \(in\) \(that\) \(light,\) \(I\) \(found\) \(deliverance\).
花了好大劲指抄代码把博客园又美化了一遍,感觉还行。
为什么前几天还在学字符串,这里就直接跳到多项式了?
我不会告诉你是因为我看不懂后缀自动机
题目简介
洛谷传送门
对原描述做了一点小优化,保证像我一样的颓废高一生能看懂。
题目描述
已知\(n\) 个点 \((x_i,y_i)\) 可以唯一地确定一个多项式 \(y = f(x)\)。
现在,给定这 \(n\) 个点,请你确定这个多项式,并求出 \(f(k) \bmod 998244353\) 的值。
输入格式
第一行两个整数 \(n,k\)。
接下来 \(n\) 行,第 \(i\) 行两个整数 \(x_i,y_i\)。
输出格式
一行一个整数,表示 \(f(k) \bmod 998244353\) 的值。
数据范围
\(1 \le n \leq 2\times 10^3\),\(1 \le x_i,y_i,k \le 998244353\),\(x_i\) 两两不同。
嗯,这题就是套公式。
证明什么的网上到处都有,这里就不写了。(真懒
然后就是实现的问题。
考虑到作除法在取模上有问题,所以用乘法逆元代替。
由于\(998244353\)是质数,套用费马小定理(当且仅当\(p\)为质数时成立):
两边同时除以\(a\),有
这样就能愉快地计算了。
注意多取亿次模就行了,不要觉得时间复杂度太高,毕竟这数据范围真的很小。
严重怀疑这范围是拿来卡高斯消元的高斯:\(mmp\)
代码如下:
//注:为跟上CCF的最新环境规定,今后所有代码均在C++14(GCC 9)和-O2优化下编译运行。
#include<cstdio>
#define ll long long
#define mod 998244353
#define maxn 2050
struct coord
{
ll x,y;
}edge[maxn];//为什么写结构体?因为无聊
ll n,k,ans;
inline ll read()
{
ll x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
inline ll Quickpow(ll x,ll n)//快速幂取模
{
ll res=1;
while(n)
{
if(n%2==1)res=res*x%mod;
x=x*x%mod;
n/=2;
}
return res;
}
inline ll inverse(ll x)//费马逆元
{
return Quickpow(x,mod-2);
}
int main()
{
n=read(),k=read();
for(register int i=1;i<=n;i++)
edge[i].x=read(),edge[i].y=read();
for(register int i=1;i<=n;i++)
{
ll s1=edge[i].y,s2=1;
for(register int j=1;j<=n;j++)
if(i!=j)
s1=s1*(k-edge[j].x)%mod,s2=s2*(edge[i].x-edge[j].x)%mod;
ans=(ans+s1*inverse(s2)%mod)%mod;
}
printf("%lld",(ans+mod)%mod);
return 0;
}
题后闲话
\(NOIp2021\)的分数线和成绩都已经正式出了,恭喜我们学校两位参加的大佬拿下一等。
今年1=分数线只有\(105pts\),非常后悔,毕竟\(T1\)打表\(T2\)记忆化搜索就能拿到\(130pts\)+了。
明年再战吧!