題解 微信步數

2022-03-30 07:42:55 字數 4347 閱讀 4410

題目鏈結

如果將每一維度都合在一起考慮,複雜度貌似無論如何都需要帶上乙個 \(\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程序本身,達到修改的目的。據作者自己所說,這個想...

刪數問題 題解

本題使用貪心思想 乙個讓這串數字越小,它的高位數就得越小。我們每次刪除要使得刪除後的數高位盡量的小。每一次刪除時,從最高位開始向低位數遍歷,當遇到的一位數比它的更高位更小時,我們就刪除它的更高一位,讓這個更小的數 篡位 就可以保證這串數更小。下一次刪除時,要也從新從最高位開始。需要注意的地方 刪除了...