zoukankan      html  css  js  c++  java
  • 牛客多校第一场 F Sum of Maximum

    题目链接

    https://www.nowcoder.com/acm/contest/139/F

    分析

    枚举i从1到a[i]的最大值,每个段考虑i的贡献。
    关键在于要在O(n)或者O(nlogn)时间内求出一个最高次为n次的多项式在x(x<=1e9)处的值来,可以利用拉格朗日差值。
    首先求出将要计算的函数在x=1,2,3.....m+1(最高次为m次)处的函数值,然后用拉格朗日差值的公式就可以求出在任意一点处函数值

    代码

    #include <iostream>
    #include <cmath>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <queue>
    #include <map>
    #include <ctime>
    using namespace std;
    typedef long long ll;
    const ll MOD=1e9+7;
    const int maxn=100050;
    int a[maxn];
    ll x[maxn];
    ll y[maxn];
    ll inv[maxn];
    ll Pow(ll x,ll n) {
    	ll ans=1,base=x%MOD;
    	if(base<0) base+=MOD;
    	while(n) {
    		if(n&1) ans=ans*base%MOD;
    		base=base*base%MOD;
    		n>>=1;
    	}
    	return ans;
    }
    void init() {
    	ll f=1;
    	for(int i = 1; i < maxn; ++i) f=f*i%MOD;
    	inv[maxn-1]=Pow(f,MOD-2);
    	for(int i = maxn-2; i >= 0; --i) {
    		inv[i]=inv[i+1]*(i+1)%MOD;
    	}
    }
    ll lagrange(ll p,int m) {
    	if(p<=m) return y[p];
    	ll tot=1;
    	ll ans=0;
    	ll pre[m+2],suf[m+2];
    	pre[0]=suf[m+1]=1;
    	for(int i = 1; i <= m; ++i){
    		pre[i]=pre[i-1]*(p-x[i])%MOD;
    		suf[m-i+1]=suf[m-i+2]*(p-x[m-i+1])%MOD;
    	}
    	for(int i = 1; i <= m; ++i) {
    		ll t=pre[i-1]*suf[i+1]%MOD;
    		t=t*inv[i-1]%MOD*inv[m-i]%MOD;
    		t=t*y[i]%MOD;
    		if((m-i)&1) t=-t;
    		ans+=t;
    	}
    	ans%=MOD;
    	if(ans<0) ans+=MOD;
    	return ans;
    }
    int main() {
    	//freopen("in.txt","r",stdin);
    	int n;
    	init();
    	while(scanf("%d", &n)!=EOF){
    		for(int i = 1; i <= n; ++i) scanf("%d", a+i);
    		sort(a+1,a+n+1);
    		a[0]=0;
    		ll pro=1,ans=0;
    		for(int i = 1; i <= n; ++i) {
    			int m=n+4-i;
    			for(int j = 1; j <= m; ++j) {
    				x[j]=j;
    				y[j]=(Pow(x[j],n-i+1)-Pow(x[j]-1,n-i+1))%MOD;
    				y[j]=y[j]*x[j]%MOD;
    				if(y[j]<0) y[j]+=MOD;
    			}
    			for(int j = 1; j <= m; ++j) {
    				y[j]=(y[j]+y[j-1])%MOD;
    			}
    			ll t=lagrange(a[i],m)-lagrange(a[i-1],m);
    			t%=MOD;
    			ans=(ans+pro*t%MOD);
    			pro=pro*a[i]%MOD;
    		}
    		ans=(ans%MOD+MOD)%MOD;
    		printf("%lld
    ", ans);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    code#5 P2 棋子
    code#5 P1 报告
    ztz11的noip模拟赛T3:评分系统
    20181101noip模拟赛T1
    20181031noip模拟赛T2
    20181031noip模拟赛T1
    Linux进程的五个段
    进程和线程有什么区别
    shell中if条件字符串、数字比对,[[ ]]和[ ]区别
    Python实现单例模式
  • 原文地址:https://www.cnblogs.com/sciorz/p/9348352.html
Copyright © 2011-2022 走看看