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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【数位DP】好数(jzoj 1521)

發(fā)布時間:2023/12/3 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【数位DP】好数(jzoj 1521) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

好數(shù)

jzoj 1521

題目大意:

定義好數(shù)為轉(zhuǎn)換為二進(jìn)制后,有至少三個連續(xù)的位相同的數(shù),現(xiàn)在要求一個范圍內(nèi)的好數(shù)個數(shù)

樣例輸入

0 16

樣例輸出

5

數(shù)據(jù)范圍限制

0 <= Low <= UP <= 2147483647

提示

提示:

對于50%測試,0 <= Low <= UP <= 100000。

解題思路:

我們可以用前綴和來求,就把問題轉(zhuǎn)換為了前n個數(shù)中好數(shù)的個數(shù)
它讓我們求好數(shù),但因為好數(shù)特別難求,所以我們可以求‘壞數(shù)’,就是沒有連續(xù)三個位是一樣的數(shù)
我們先用數(shù)位DP求出多少位以什么開頭的壞數(shù)總數(shù)
然后我們把他分位數(shù)小于n的位數(shù)的和等于n的位數(shù)的
小于的:
我們就可以直接用已經(jīng)求出來的壞數(shù)總數(shù),然后分為不同位數(shù)的直接加就行了
如1…1100100先分為1位,2位,3位,4位,5位,6位的類型
等于的:
就從大到小把1變成0,這樣就一定小于n了,然后分別計算
最后還要計算n
然后用n減去壞數(shù)的個數(shù)就得到了好數(shù)的個數(shù)了

代碼:

#include<cstdio> #include<cstring> #include<iostream> #define ll long long using namespace std; ll a,b,s[40],f[40][5][5]; ll js(ll now) {ll sum=1;for (int i=now-1;i>0;--i)sum+=f[i][1][0]+f[i][1][1];//小于的(第一類)for (int i=now-1;i>0;--i){if (s[i]==1)if (s[i+1]==1||s[i+2]==1||i==now-1)//把1改為0sum+=f[i+1][s[i+1]][0];相加if (s[i]==s[i+1]&&s[i+1]==s[i+2]&&i!=now-1)//判斷是不是已經(jīng)成為了好數(shù)了{sum--;break;}}return sum; } ll ans(ll dep) {if (dep<=0) return 0;ll l=dep,tot=0;memset(s,0,sizeof(s));while (l) s[++tot]=l&1,l>>=1;//轉(zhuǎn)二進(jìn)制return dep-js(tot);//求好數(shù) } int main() {f[1][1][0]=1;f[1][0][1]=1;for (int k=2;k<=35;++k){f[k][0][0]=f[k-1][0][1];//數(shù)位DPf[k][0][1]=f[k-1][1][1]+f[k-1][1][0];f[k][1][0]=f[k-1][0][0]+f[k-1][0][1];f[k][1][1]=f[k-1][1][0];}scanf("%lld %lld",&a,&b);printf("%lld",ans(b)-ans(a-1));//前綴和求職 } 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結(jié)

以上是生活随笔為你收集整理的【数位DP】好数(jzoj 1521)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。