題目鏈結
如果將每一維度都合在一起考慮,複雜度貌似無論如何都需要帶上乙個 \(\prod_^kw_i\) ,類似 csp2020t3 的思路,如果把每一維都分開考慮可能可以降低一點複雜度。
對於維度 \(i\) 的某乙個位置 \(p(1\le p\le w_i)\) ,我們可以求出乙個值 \(\mbox_i(p)\) 表示在僅考慮維度 \(i\) 時小 c 走出場地需要的最少步數,如果小 c 無論如何都無法走出場地那麼 \(\mbox_i(p)=+\infty\) ,求出 \(\mbox\) 這個函式之後,小 c 從 \((a_1,a_2,\dots,a_k)\) 走出場地需要的步數就是 \(\min_^k\mbox_i(a_i)\) 。
對於某一維度 \(i\) ,我們並不關心 \(\mbox_i(1\dots w_i)\) 這個數列所有值之間的順序,所以我們可以給 \(\mbox_i(1\dots w_i)\) 先排個序。
我們需要求的東西是:
\[\sum_\min_^k\mbox_i(a_i)=\sum_\prod_^k(\sum_^[\mbox_j(t)\ge i])
\]直接求出所有的 \(\mbox_i(j)\) ,然後從小到大列舉每乙個 \(\mbox_i(j)\) 就可以很容易求出上面這個式子的值了,此時我們就成功地將 \(\prod_^kw_i\) 的複雜度降為了 \(\sum_^kw_i\) 了,按照實現不同複雜度此時可以達到 \(\mathcal o((\sum_^kw_i)\log_2(\sum_^kw_i))\) 或 \(\mathcal o(k(\sum_^kw_i))\) 或 \(\mathcal o((\sum_^kw_i)\log_2 k)\) ,應該可以拿到 \(80\rm pts\) 。
要拿更高的分數,需要進一步觀察 \(\mbox_i(1\dots w_i)\) 這個數列的性質,可以找到兩個數列 \(\mbox_i(1\dots p_i)\) 以及 \(\mbox_i(1\dots s_i)\) 使得 \(\mbox_i(1\dots w_i)\) 是數列 \(\mbox_i(1\dots p_i)\) 和數列 \(\mbox_i(1\dots s_i)\) 不斷重複同時加上若干倍的 \(n\) 得到的:
\[\mbox_i(1),\dots,\mbox_i(p_i),\mbox_i(1)+n,\dots,\mbox_i(s_i)+n,\mbox_i(1)+2n,\dots,\mbox_i(s_i)+2n,\mbox_i(1)+3n,\dots,\mbox_i(1)+tn,\dots
\]並且上面這個序列是排好序的,有 \(\mbox_i(j)\le n,\mbox_i(j)\le n\) 。
由於 \(\sum_^kp_i\le n\) ,所以我們可以用上面的方法求出 \(\mbox_i()\) 數列這一段的值,即這個式子的值:
\[\sum_^n\prod_^k(\sum_^[\mbox_j(t)\ge i])
\]需要注意的是 \(\mbox_i()\) 這個數列重複是一直重複到 \(w_i\) 為止的,如果把 \(\mbox_i(1)+tn,\dots \mbox_i(s_i)+tn\) 稱作是一輪的話,那麼可能最後並不能湊成一整輪,由於 \(\sum_^ks_i\le n\) ,所以無法湊夠一整輪的這一部分也可以單獨算,關鍵是算中間重複著的若干輪。
中間重複著的若干輪數列之間的 \(\mbox_i()\) 的大小關係都是固定的,所以我們只需要模擬第一輪其實就已經模擬了所有輪了。
假設重複的輪數為 \(r\) ,對於當前列舉的某乙個 \(i\) , \(c_j=\sum_^[\mbox_j(t)\ge i]\) ,那麼此時造成貢獻需要乘以的係數應該是這個:
\[\sum_^\prod_^k(c_j-t\cdot s_i)=\sum_^\sum_(-t)^\prod_s_j\prod_c_j=\sum_\prod_s_j\prod_c_j(-1)^\sum_^t^
\]令:
\[f(x)=(-1)^x\sum_^t^x,dp(x)=\sum_\prod_s_j\prod_c_j
\]那麼要求的就是:
\[\sum_^kf(x)dp(x)
\]如何求 \(f(x)\) ?自然數冪求和,設 \(s_k(n)=\sum_^ni^k\) :
\[s_k(n)=\sum_^ni^k=\sum_^n\sum_^kj!=\sum_^kj!
\]直接 \(\mathcal o(k^2)\) 求即可(當然可以用一些其它的方式求,這裡不多說)。
如何求 \(dp(x)\) ?顯然可以 \(dp\) 求,設 \(dp(i,x)\) 表示僅考慮前 \(i\) 個數的答案,那麼轉移就是考慮當前這個數是否包含在集合內:
\[dp(i,x)=dp(i-1,x)\times c_i+dp(i-1,x-1)\times s_i
\]最後的 \(dp(x)=dp(k,x)\) 。
如果每次都做一次 \(dp\) ,單次時間複雜度是 \(\mathcal o(k^2)\) 的,總的時間複雜度就是 \(\mathcal o(nk^2)\) 的,應該可以過,但是可以更優,不難發現這個 \(dp\) 是可撤銷的,也就是我們可以刪除乙個數,即:
\[dp(i-1,x)=(dp(i,x)-dp(i-1,x-1)\times s_i)\div c_i
\]由於每次我們只會更改某乙個位置 \(v\) ,即令 \(c_v\gets c_v-1\) ,所以我們可以先撤銷 \(v\) 造成的影響,然後更新完 \(c_v\) 後再加上 \(v\) 造成的影響,這樣就不需要每次都 \(dp\) 一遍,單詞時間複雜度降為 \(\mathcal o(k)\) ,總時間複雜度為 \(\mathcal o(nk)\) 。
如果算上所有操作,總時間複雜度就是 \(\mathcal o(k^2+n(k+\log_2w))\) 的。
總感覺自己把挺簡單的乙個東西講得好複雜啊。
#include#include#include#includeusing namespace std;
#define ch() getchar()
#define pc(x) putchar(x)
templatevoid read(t&x)
templatevoid write(t x)
const int mod=1000000007,maxn=500006,maxk=12;
int mo(const int x)
int power(int a,int x)
return re;
}int cnto[maxk][maxn],cntr[maxk][maxn];
int pos[maxk],w[maxk];
int abs(int x)
int num[maxk][maxn],p[maxk],pn[maxk];
int sum[maxk][maxn],s[maxk],cn[maxk];
int _s[maxk][maxk],f[maxk];
int dp[maxk];
void chkmin(int&x,int y)
int main()
int ok=true,rd=0x3f3f3f3f;
for(int i=1;i<=k;++i)
if(pos[i]<0)
} if(s[i]>0)
} if(ok)return puts("-1"),0;
f[0]=rd;_s[0][0]=1;
for(int i=1;i<=k;++i)
for(int j=0;j=0x3f3f3f3f)
ans=mo(ans+1ll*(mn-pre)*all%mod);
all=1ll*all*power(w[mp]-pn[mp],mod-2)%mod;
++pn[mp];all=1ll*all*(w[mp]-pn[mp])%mod;
pre=mn;
} dp[0]=1;
for(int i=1;i<=k;++i)
pre=0;
while("imakf ak ioi")
ans=mo(ans+1ll*(mn-pre)*add%mod);
++pn[mp];int i=power(cn[mp],mod-2);
for(int i=k;i>=1;--i)
dp[i]=1ll*mo(mod-1ll*dp[i+1]*s[mp]%mod+dp[i])*i%mod;
--cn[mp];
for(int i=1;i<=k;++i)
dp[i]=mo(1ll*dp[i]*cn[mp]%mod+1ll*dp[i+1]*s[mp]%mod);
pre=mn;
} all=1;
for(int i=1;i<=k;++i)
pre=0;
while("imakf ak ioi")
write(ans),pc('\n');
return 0;
}
NOIP2020微信步數
luogu 定義0 c i,d i 與題意中相同 令 d 為題意中的 k 即維數。定義1 令 i,j 為第 i 輪第 j 步。定義2 對於 i,j 如果存在位置此時走出界限,則稱其為最值。令最值集合為 s 定義3 令向量 vec 為一輪後各維的增量 定義4 容易發現,forall i,j in s ...
零門檻修改微信步數(基於虛擬xposed)
效果大概就是只需3分鐘,全校第一不是夢吧。感謝不知道哪個學校的的小夥伴友情提供截圖。介紹 只想看教程的請往下拉 搬運乙個新操作。隆重介紹劃時代的新技術,虛擬xposed exposed 大佬作品,是通過虛擬 雙開 技術,讓應用在沙盒內執行,從而hook程序本身,達到修改的目的。據作者自己所說,這個想...
刪數問題 題解
本題使用貪心思想 乙個讓這串數字越小,它的高位數就得越小。我們每次刪除要使得刪除後的數高位盡量的小。每一次刪除時,從最高位開始向低位數遍歷,當遇到的一位數比它的更高位更小時,我們就刪除它的更高一位,讓這個更小的數 篡位 就可以保證這串數更小。下一次刪除時,要也從新從最高位開始。需要注意的地方 刪除了...