我们仍未知道那天所看见的题的解法 - 3
CF622F The Sum of the k-th Powers
【分析过程】
求 \(\sum\limits_{i=1}^ni^k\)?超级简单傻逼题,容我慢慢打个快速幂,\(O(n\lg k)\) 秒了
傻逼竟是我自己
首先对于 \(\sum\limits_{i=1}^ni^k\),这叫做自然数幂之和,在具体数学的伯努利数那一节出现过,可以证明答案是 \(k+1\) 次方的多项式
这里我们不用伯努利数,我们用2020省选中那个东西
仿照2020省选A卷中普通幂转下降幂
这里也有个关于阶乘转下降幂的恒等式
这在具体数学中有证明,但在我证明完毕之前并没有看到(也就是说刚证出来就看见了QAQ,它那里证的比我简洁,是巨简洁)
接下来我们自己来使用数学归纳法证一下
显然当 \(k=1,k=2\) 时成立,将 \(i^k\) 与 \(i^{k-1}\) 做差,也就是说我们只需要证明
这东西显然是可以双向推出的,于是我们不关心从哪个方向证明
即得:
设 \(S(n)=\sum\limits_{i=1}^ni^k\),应用上指标求和:
我们并不关心这个多项式是什么,我们只要知道它在 \(S(n)\) 下的取值
于是我们可以直接找出 \(k+2\) 个点,暴力拉格朗日插值即可得出答案
但是这样复杂度就会爆炸,然后你需要多项式快速插值
观察拉格朗日插值的式子:
我们发现复杂度的瓶颈在后面的 \(\prod\) 上,这道题并没有给我们点值,所以我们可以自己决定
于是我们可以选取一段 \(x\) 连续的 \(k+2\) 个点值,此时式子变为
对于分子进行预处理之后,直接上 \(\text{Lagrange}\) 插值即可
【代码实现】
#include<bits/stdc++.h>
#define fx(l,n) inline l n
#define int long long
const int mod=1e9+7,N=1200000;
int n,k,fac[N],sum[N],bf,ans,low[N],inv[N],dinv[N];
fx(int,gi)(){
char c=getchar();int s=0,f=1;
while(c>'9'||c<'0'){
if(c=='-') f=-f;
c=getchar();
}
while(c<='9'&&c>='0') s=(s<<3)+(s<<1)+(c-'0'),c=getchar();
return s*f;
}
fx(int,fpow)(int a,int b=mod-2){
int sum=1;
while(b){
if(b&1) (sum*=a)%=mod;
(a*=a)%=mod;
b>>=1;
} return sum;
}
signed main(){
n=gi(),k=gi();fac[0]=1;
for(int i=1;i<=k+10;i++) fac[i]=fac[i-1]*i%mod;
inv[k+2]=fpow(fac[k+2]);
for(int i=k+1;~i;i--) inv[i]=inv[i+1]*(i+1)%mod;
for(int i=1;i<=k+2;i++) sum[i]=(sum[i-1]+fpow(i,k))%mod;
if(n<=k+2) return printf("%lld",sum[n]),0;
low[1]=n-1;
for(int i=2;i<=k+2;i++) low[i]=low[i-1]*(n-i)%mod;
for(int i=1;i<=k+2;i++) dinv[i]=fpow(n-i);
for(int i=1;i<=k+2;i++){
bf=sum[i]*inv[i-1]%mod*inv[k-i+2]%mod*dinv[i]%mod;
if((k+2-i)&1) ans+=mod-bf;
else ans+=bf;
ans%=mod;
}
printf("%lld",ans*low[k+2]%mod);
}
CF576D Flights for Regular Customers
【分析过程】
一个经典题目
首先这题不能直接矩阵快速幂,因为边有限制
考虑到边并不是很多,于是我们可以分开进行快速幂
也就是说每次加边,然后快速幂直到下一条边的限制解除,然后以此类推
考虑乘法过程即为:\(ans\times m\times m\times\cdots\times m\),加边,继续乘 \(m\)
于是乎 \(ans\) 矩阵可以不用每次重置
对于每次快速幂后,判断可达性,之后跑个最短路更新一下答案
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<bitset>
#define N 1000001
#define M 201
#define INF 20000000000
#define Kafuu return
#define Chino 0
#define fx(l,n) inline l n
#define set(l,n,ty,len) memset(l,n,sizeof(ty)*len)
#define cpy(f,t,ty,len) memcpy(t,f,sizeof(ty)*len)
#define int long long
#define R register
#define C const
using namespace std;
int n,m,last,dis[M][M],ans=INF;
struct matrix{
bitset<M>m[M];
fx(matrix,operator) * (const matrix &b) const{
matrix c;
for(int i=1;i<=n;i++){
for(int o=1;o<=n;o++) c.m[i][o]=0;
for(int o=1;o<=n;o++){
if(m[i][o]) c.m[i]|=b.m[o];
}
}
return c;
}
}ma,dw;
struct Edge{
int f,t,tms;
}e[N];
fx(bool,cmp)(Edge a,Edge b){
return a.tms<b.tms;
}
fx(int,gi)(){
R char c=getchar();R int s=0,f=1;
while(c>'9'||c<'0'){
if(c=='-') f=-f;
c=getchar();
}
while(c<='9'&&c>='0') s=(s<<3)+(s<<1)+(c-'0'),c=getchar();
return s*f;
}
fx(void,pow)(int b){
while(b){
if(b&1) dw=dw*ma;
ma=ma*ma;
b>>=1;
}
}
fx(void,stcmt)(int b){
for(int i=1;i<=n;i++){
for(int o=1;o<=n;o++){
dis[i][o]=(i==o?0:INF);
}
}
for(int i=1;i<=b;i++) dis[e[i].f][e[i].t]=1;
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int o=1;o<=n;o++){
dis[i][o]=min(dis[i][o],dis[i][k]+dis[k][o]);
}
}
}
}
signed main(){
n=gi(),m=gi();
for(int i=1;i<=m;i++){
e[i].f=gi(),e[i].t=gi();e[i].tms=gi();
}
for(int i=0;i<=n;i++) dw.m[i][i]=1;
sort(e+1,e+m+1,cmp);
for(int i=1;i<=m;i++){
for(int o=1;o<=n;o++) ma.m[o].reset();
for(int o=1;o<i;o++) ma.m[e[o].f][e[o].t]=1;
pow(e[i].tms-e[i-1].tms);
stcmt(i);
for(int o=1;o<=n;o++){
if(dw.m[1][o]) ans=min(ans,e[i].tms+dis[o][n]);
}
}
if(ans==INF) printf("Impossible");
else printf("%d",ans);
}