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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

???--???二进制变换

發布時間:2023/12/10 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ???--???二进制变换 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題意 :

定義兩種變換?

1 : i = i - 1

2 : i = i - lowbit (i)

?

定義函數Calc(i,j)為二進制意義下 i 變換到 j 的最小步數。

給你一個二進制整數 n,要求 sigma {(i = 1 -> n) sigma {(j = 0 -> i - 1) Calc (i,j)}}

數據范圍 :?

令n的長度為len

len <= 1000000

-----------------------------------------------此后一千里-----------------------------------------------------

?

?

?

?

?

?

?

?

?

?

?

?

?

?

首先有一個很顯然的性質,就是如果 i 用了2操作之后還比 j 大的話,那么一定用2操作,因為減去lowbit不比減去1差

我們設 f(n) = sigma {(i = 0 -> n-1) Calc (n,i)},

我們考慮將n按位處理掉,設t(n)為n只保留的二進制最高位的數,我們發現對于Calc (n,i) 如果 t(n) == t(i) 那么答案顯然是 Calc (n-t(n),i-t(i))

而如果 t(n)!=t(i) 那么我們無論如何要把 n 變換到 i 都必須把 n 變換到 t(n) ,而顯然 t(n)!=t(i) 的 i 有 t(i) 個.

所以我們便可以將 f(n) 拆分掉得到 f(n) = t(n) * (BitCount(n) - 1) + f( n - t(n)),我們可以一直拆下去,也就是說我們只用算2的整次冪的 f 就可以了。

假設我們已經求出2的0-3次冪,要求 f (10000) , 因為除了變換到0,10000變換到任何數都要先變換到1111,所以我們可以得到下式 :

f(10000) = f(1111) + 1111 - 4 + 1 減4加1意思是去掉1111變到0的代價,加上10000變到0的代價

我們將f(1111) 再展開即可得到 f 關于2的整次冪的遞推式,前綴和優化一下可以O(n)預處理

設 g(n) = sigma{(i = 1 -> n) f(i)},g(n)求的實際上就是答案

我們還是考慮去按位處理掉

g(n) = $\sum \limits_{i = 1}^{t(n)-1} f(i) + \sum \limits_{i = t(n)}^{n} f(i)$

  = $g(t(n) - 1) + \sum \limits_{i = t(n)}^{n} f(i)$

我們考慮將后面sigma中的 f(i) 中的 f(t(n)) 及t(n)相關的常數項全部提取出來,那么后面就可以提取出 (n-t(n)+1) 個 f(t(n)),常數項的話先暫時用k(n-t(n))表示,提取后剩下的部分就是 g(n-t(n))。

然后g(n) = g(t(n) - 1) + (n-t(n)+1)*f(t(n)) + k(n-t(n)) + g(n-t(n))

如果我們可以處理 k(n-t(n)) 和 g(t(n) - 1) 的話,就可以在復雜度要求內得出解了

我們考慮如何去求 k ,觀察后發現 k 函數的實際意義可以表達為 k(n) = $\sum \limits_{i = 0}^{n} BitCount(i)$

用和 g 相似的手法,我們也可以把 k 給拆分到只于2的整次冪減1項相關

因為我們常數項的系數就是BitCount()的和

當n=2^a - 1時我們把式子變形得到k(n) = $\sum \limits_{i = 1}^{a} \binom{a}{i} * a = a * 2^{a - 1}$就很好處理了

然后我們發現 g 的2的整次冪減1是也可以方便預處理的,也是相似的手法,就不再贅述了

然后就可以預處理f,g,k,然后就可以計算答案了

計算答案時可以從后往前很方便的計算?

代碼 :

/* Lelouch vi Britannia here commands you , all of you , die ! */ #include<bits/stdc++.h> #define INF 0x3f3f3f3f #define low(x) ((x)&(-(x))) #define LL long long #define eps 1e-9 #define MOD 1000000007 using namespace std;#define int int inline int Max(int a,int b) {return a>b?a:b;} inline int Min(int a,int b) {return a<b?a:b;} inline int Abs(int a) {return a>0?a:-a;} inline int Sqr(int a) {return a*a;} #undef int#define MAXN 1000006int n; LL f[MAXN],g[MAXN],k[MAXN],two[MAXN],md[MAXN],uk[MAXN],ug[MAXN]; char s[MAXN];void Pre(int n) {two[1]=1;g[1]=1;f[1]=1;k[1]=1;f[2]=2;for(int i=2;i<=n;i++) two[i]=two[i-1]*2%MOD;for(int i=3;i<=n;i++) f[i]=(2*f[i-1]+(i-1)*two[i-1]-1)%MOD;for(int i=2;i<=n;i++) k[i]=(k[i-1]*2+two[i])%MOD;for(int i=2;i<=n;i++) g[i]=(g[i-1]*2+two[i]*f[i]+k[i-1]*two[i])%MOD;for(int i=1;i<=n;i++) {md[i]=(md[i-1]+(s[n-i]=='1'?two[i]:0))%MOD;uk[i]=(uk[i-1]+(s[n-i]=='1'?md[i-1]+1+k[i-1]:0))%MOD;ug[i]=(ug[i-1]+(s[n-i]=='1'?md[i-1]*f[i]%MOD+f[i]+uk[i-1]*two[i]%MOD+g[i-1]:0))%MOD;} }int main() {scanf("%s",s);n=strlen(s);Pre(n);printf("%lld\n",ug[n]);return 0; } /* Hmhmhmhm . That's right , I am killer. */ View Code

?

轉載于:https://www.cnblogs.com/ihopenot/p/6606954.html

總結

以上是生活随笔為你收集整理的???--???二进制变换的全部內容,希望文章能夠幫你解決所遇到的問題。

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