JZOJ 5395. 【NOIP2017提高A组模拟10.6】Count

来源:互联网 发布:jdk 7 windows i586 编辑:程序博客网 时间:2024/05/21 03:55

题目

这里写图片描述

题解

①我们可以知道当x2时,φ(x)为偶数。
②我们亦可以知道当gcd(x,y)=1时,gcd(x,yx)=1
由①,②得,当x2时,f(x)=x。特别的,f(1)=2
问题转换为ΣRi=Lik(1)
新知识:拉格朗日插值法求自然数幂和。
这东西干嘛用?
假设有一个平面直角坐标系,那么有k+1个点(x0,f(x0)),...,(xk,f(xk))
用这k+1个点就可以确定一个k次的多项式。
li(x)表示拉格朗日基本多项式li(x)=Πk+1j=1,jixxjxixj
接下来说明f(x)=Σk+2i=1f(i)li(x)为什么是对的。
首先f(x)=Σxi=1ik可以等于一个k+1次的关于x的多项式。
我们只要证明当x=1...k+2时式子成立,那么这个k+1次的多项式就是确定的。
我们可以知道当x=xi时,li(x)=1,否则li(x)=0
(我们可以将x带进l_i(x)中,若xxi,那么l_i(x)的有一个分子的因式等于0。)
在这道题目中,xi=i,因为f(1)...f(i)...f(k+2)可求,每一个i都相当于多项式的图象经过的第i个点,所以xi=i
因为只有i=j时,f(j)li(j)0
所以等式的左边f(i)=Σk+2j=1,jif(j)li(j)=f(i)等于等式的右边。
得证。
证明的大致思路:确定对x=1...k+2成立→确定这个唯一的k+1次的多项式→确定f(n)
别忘记L=1时要特判。

代码

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#define LL long long#define N 1000010#define mo 998244353#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;LL i,L,R,x,k,sum1,sum2,sum;LL n0,n1,n2;LL jc[N],ny[N];LL f[N]; LL ksm(LL x,LL y){    LL res=1;    for(;y;x=(x*x)%mo,y/=2)if(y&1)res=(res*x)%mo;    return res; }void get(){    LL i,temp;    jc[0]=jc[1]=ny[0]=ny[1]=1;    fo(i,2,1000002)jc[i]=(jc[i-1]*i)%mo;    fo(i,2,1000002)ny[i]=ksm(jc[i],mo-2);    temp=0;    fo(i,1,1000002){        temp=(temp+ksm(i,k))%mo;        f[i]=temp;    }}LL getsum(LL n){    if(n<=k+2)return f[n];    LL i,temp,temp1,inv,inv1,inv2,n0,n1,n2,sum3=0;    n0=1;    fo(i,1,k+2)n0=(n0*(n-i))%mo;    fo(i,1,k+2){        temp=(n0*f[i])%mo;        inv1=((jc[i-1]*(n-i))%mo*jc[k-i+2])%mo;        inv1=ksm(inv1,mo-2);        temp1=(temp*inv1)%mo;        if((k+2-i)&1)sum3=(sum3-temp1+mo)%mo;        else sum3=(sum3+temp1)%mo;    }    return sum3;}int main(){    freopen("count.in","r",stdin);    freopen("count.out","w",stdout);    scanf("%lld%lld%lld",&L,&R,&k);    get();    sum1=getsum(R);    sum2=getsum(L-1);    sum=(sum1-sum2+mo)%mo;    if(L==1)sum=(sum+ksm(2,k)-1+mo)%mo;    printf("%lld",sum);    return 0;}
原创粉丝点击