日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

P7962-[NOIP2021]方差【dp,差分】

發布時間:2023/12/3 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 P7962-[NOIP2021]方差【dp,差分】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

正題

題目鏈接:https://www.luogu.com.cn/problem/P7962


題目大意

給出一個長度為nnn的序列aaa,你每次可以讓一個ai(1<i<n)=ai?1+ai+1?aia_i(1<i<n)=a_{i-1}+a_{i+1}-a_iai?(1<i<n)=ai?1?+ai+1??ai?,求能變出的最小方差。

1≤n≤400,1≤ai≤6001\leq n\leq 400,1\leq a_i\leq 6001n400,1ai?6001≤n≤104,1≤ai≤501\leq n\leq 10^4,1\leq a_i\leq 501n104,1ai?50


解題思路

民間數據過了就當過了吧

這個式子顯然我們可以差分之后變成交換相鄰的數,讓所有的數都減去a1a_1a1?這樣方差不變并且第一個保證為000,然后我們記差分數組bi=ai+1?aib_i=a_{i+1}-a_ibi?=ai+1??ai?,那么化一下答案的式子就是
n∑i=1nai2?(∑i=1nai)2?n∑i=1n?1(∑j=1ibj)2?(∑i=1n?1bi(n?i))2n\sum_{i=1}^na_i^2-\left(\sum_{i=1}^na_i\right)^2\Rightarrow n\sum_{i=1}^{n-1}\left(\sum_{j=1}^{i}b_j\right)^2-\left(\sum_{i=1}^{n-1}b_i(n-i)\right)^2ni=1n?ai2??(i=1n?ai?)2?ni=1n?1?(j=1i?bj?)2?(i=1n?1?bi?(n?i))2

這個式子乍一眼我們看不出什么,但是我們可以得到每個bib_ibi?對之間乘積的權重記為fi,jf_{i,j}fi,j?,會發現fi,jf_{i,j}fi,j?是按照i/ji/ji/j相互之間越接近/越接近中間而遞增的,但是依然會出現一些邊邊的靠近數對的情況比中間的不那么靠近數對的權重要高。

一個直觀的想法是類似于一個山谷之類的填法,打幾個表之后不難發現確實是從一個點往兩邊遞增的規律。

考慮在此基礎上進行dpdpdp,考慮在一個填好的序列的前面/后面加上一個數字會產生的變化,記ansansans為原來的答案,記LLL為題目中給出的nnn(因為目前我們還沒有放完nnn個數字,所以此時的nnn不一樣),xxx為插入的數組。

  • 插在前面:
    L∑i=1n?1(∑j=1ibj+x)2?(nx+∑i=1n?1bi(n?i))2L\sum_{i=1}^{n-1}\left(\sum_{j=1}^{i}b_j+x\right)^2-\left(nx+\sum_{i=1}^{n-1}b_i(n-i)\right)^2Li=1n?1?(j=1i?bj?+x)2?(nx+i=1n?1?bi?(n?i))2
    ?ans+Lnx2+2Lx∑i=1n?1bj?2nx∑i=1n?1bi(n?i)?n2x2\Rightarrow ans+Lnx^2+2Lx\sum_{i=1}^{n-1}b_j-2nx\sum_{i=1}^{n-1}b_i(n-i)-n^2x^2?ans+Lnx2+2Lxi=1n?1?bj??2nxi=1n?1?bi?(n?i)?n2x2
  • 插在后面:
    L(∑i=1n?1(∑j=1ibj)2+(x+∑i=1n?1bi)2)?(x+∑i=1n?1bi+∑i=1n?1bi(n?i))2L\left(\sum_{i=1}^{n-1}\left(\sum_{j=1}^{i}b_j\right)^2+\left(x+\sum_{i=1}^{n-1}b_i\right)^2\right)-\left(x+\sum_{i=1}^{n-1}b_i+\sum_{i=1}^{n-1}b_i(n-i)\right)^2L???i=1n?1?(j=1i?bj?)2+(x+i=1n?1?bi?)2????(x+i=1n?1?bi?+i=1n?1?bi?(n?i))2
    ?ans+L(x+∑i=1n?1bi)2?(x+∑i=1n?1bi)2?2(x+∑i=1n?1bi)(∑i=1n?1bi(n?i))\Rightarrow ans+L\left(x+\sum_{i=1}^{n-1}b_i\right)^2-\left(x+\sum_{i=1}^{n-1}b_i\right)^2-2\left(x+\sum_{i=1}^{n-1}b_i\right)\left(\sum_{i=1}^{n-1}b_i(n-i)\right)?ans+L(x+i=1n?1?bi?)2?(x+i=1n?1?bi?)2?2(x+i=1n?1?bi?)(i=1n?1?bi?(n?i))

然后會發現我們很難知道∑i=1n?1bi(n?i)\sum_{i=1}^{n-1}b_i(n-i)i=1n?1?bi?(n?i)這個東西,所以考慮放進dpdpdp數組里面維護,但是如果丟進去維護了后面那個東西就完全沒有必要了,所以可以刪掉很多復雜的部分。

那么設fi,jf_{i,j}fi,j?表示目前填了iii∑i=1n?1bi(n?i)=j\sum_{i=1}^{n-1}b_i(n-i)=ji=1n?1?bi?(n?i)=j時的最小方差,然后就可以O(1)O(1)O(1)轉移了。

這樣的時間復雜度是O(n2ai)O(n^2a_i)O(n2ai?)的,可以拿到888888分,我在考場上就止步于此了。

現在來分析一下最后一個點ai≤50a_i\leq 50ai?50的性質,也就是說差分數組里面最多只有505050個數是有值的,所以有一堆000,直接動態更新dpdpdp枚舉的上界就過了。
時間復雜度:O(naimin?{ai,n})O(na_i\min\{a_i,n\})O(nai?min{ai?,n})

好不容易那么接近一次正解,你卻讓我輸的那么徹底,焯!\color{white}好不容易那么接近一次正解,你卻讓我輸的那么徹底,焯!


code

#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const ll N=5e5+10,inf=1e18; ll n,L,a[N],s[N],f[2][N],ans; signed main() {scanf("%lld",&n);if(n==1)return puts("0");for(ll i=1;i<=n;i++)scanf("%lld",&a[i]);L=n*a[n];ans=inf;for(ll i=1;i<n;i++)a[i]=a[i+1]-a[i];n--;sort(a+1,a+1+n);L=a[1];for(ll i=1;i<=n;i++)s[i]=s[i-1]+a[i];for(ll i=0;i<=L;i++)f[1][i]=inf;f[1][a[1]]=a[1]*a[1];for(ll k=2;k<=n;k++){int R=s[k]*k;for(ll i=0;i<=R;i++)f[k&1][i]=inf;for(ll i=0;i<=L;i++){if(f[~k&1][i]!=inf){f[k&1][i+a[k]*k]=min(f[k&1][i+a[k]*k],f[~k&1][i]+k*a[k]*a[k]+2ll*i*a[k]);f[k&1][i+s[k]]=min(f[k&1][i+s[k]],f[~k&1][i]+s[k]*s[k]);}}L=R;}for(ll i=0;i<=L;i++)if(f[n&1][i]!=inf)ans=min(ans,f[n&1][i]*(n+1)-i*i);printf("%lld\n",ans);return 0; } /* 10 6 19 34 35 56 63 82 82 83 99 */

總結

以上是生活随笔為你收集整理的P7962-[NOIP2021]方差【dp,差分】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。