LibreOJ2044 - 「CQOI2016」手機號碼
阿新 • • 發佈:2018-05-26
超過 AR herf des truct ret 問題 esc lint ),\(f_4\)表示是否在第\(k\)達到上限。
考慮第\(k+1\)位的每種取值\(i\)。若\(i=x\),則\(f_1=1\);若已有三連或原\(f_1=1\)且\(i=x\),則\(f_2=1\);若\(i\)等於\(4\)或\(8\),改變\(f_3\);若在第\(k\)位就達到上限且\(i\)等於n的第\(k+1\)位,則\(f_4=1\)。
用隊列進行轉移或循環每一維即可解決。
Portal
Description
給出兩個十一位數\(L,R\),求\([L,R]\)內所有滿足以下兩個條件的數的個數。
- 出現至少\(3\)個相鄰的相同數字;
- 不能同時出現\(4\)和\(8\)。
Solution
數位DP。
首先將問題轉換成\(solve(R)-solve(L)\)的形式,這樣只需要求不超過\(n\)的滿足條件的數的個數。
定義\(dp[k][x][f_1][f_2][f_3][f_4]\),其中\(k\)表示位數,\(x\)表示尾數,\(f_1\)表示第\(k\)位與第\(k-1\)位是否相同,\(f_2\)表示是否出現過三連,\(f_3\)表示\(4,8\)的出現情況(\(00,01,10,11\)
考慮第\(k+1\)位的每種取值\(i\)。若\(i=x\),則\(f_1=1\);若已有三連或原\(f_1=1\)且\(i=x\),則\(f_2=1\);若\(i\)等於\(4\)或\(8\),改變\(f_3\);若在第\(k\)位就達到上限且\(i\)等於n的第\(k+1\)位,則\(f_4=1\)。
用隊列進行轉移或循環每一維即可解決。
時間復雜度\(O(11×10×2×2×4×2\cdot10)\)。
Code
//「CQOI2016」手機號碼
#include <cstdio>
#include <cstring>
#include <queue>
typedef long long lint;
struct state
{
int k,x,f1,f2,f3,f4;
state(int _k,int _x,int _f1,int _f2,int _f3,int _f4) {k=_k,x=_x,f1=_f1,f2=_f2,f3=_f3,f4=_f4;}
};
const int LEN=11;
lint dp[12][10][2][2][4][2];
std::queue<state> Q;
int is48(int x) {return (x==8)<<1 |(x==4);}
lint solve(lint n)
{
memset(dp,0,sizeof dp);
int v[12];
for(lint i=LEN,t=n;i>=1;i--,t/=10) v[i]=t%10;
for(int i=1;i<=v[1];i++)
{
int f3=is48(i),f4=(i==v[1]);
dp[1][i][0][0][f3][f4]=1;
Q.push(state(1,i,0,0,f3,f4));
}
while(!Q.empty())
{
state s=Q.front(); Q.pop();
int k=s.k,x=s.x,f1=s.f1,f2=s.f2,f3=s.f3,f4=s.f4,val=dp[k][x][f1][f2][f3][f4];
if(k==LEN) continue;
int t=f4?v[k+1]:9;
for(int i=0;i<=t;i++)
{
int _f1=(i==x),_f2=f2||f1&&(i==x),_f3=f3|is48(i),_f4=f4&&i==t;
lint &r=dp[k+1][i][_f1][_f2][_f3][_f4];
if(!r) Q.push(state(k+1,i,_f1,_f2,_f3,_f4));
r+=val;
}
}
lint r=0;
for(int i=0;i<=9;i++)
for(int _f1=0;_f1<=1;_f1++)
for(int _f3=0;_f3<=2;_f3++)
r+=dp[LEN][i][_f1][1][_f3][0]+dp[LEN][i][_f1][1][_f3][1];
return r;
}
int main()
{
lint L,R;
scanf("%lld%lld",&L,&R);
if(L==(lint)1e10) printf("%lld\n",solve(R)-solve(L)+1);
else printf("%lld\n",solve(R)-solve(L-1));
return 0;
}
LibreOJ2044 - 「CQOI2016」手機號碼