題解:P14074 [GESP202509 五級] 有趣的數字和
感覺這題真的不止黃(可能是我太菜了<(_ _)>
這道題會讓我們聯想到數位dp(其實沒有多少關系(@_@)
這里還是借用的老師的思路
計算l-r之間有趣數字的個數,也就是0-r之間有趣數字的個數減去0-(l-1)之間有趣數字的個數
我們想想怎么計算從0~x之間一共有多少個有趣數字
另外 30% 的測試點,保證 l=1 并且 r=2^k ?1,其中 k 是大于 1 的正整數。
題目中的這個有提示意義的數據告訴我們,2^k-1可以直接計算(或推出來), 這樣我們就可以試著將數拆成類似于2^k-1的形式
like this

代碼放上,如果有什么問題記得@我
https://www.luogu.com.cn/discuss/1165743
還有我關于這道題有些問題,希望大佬解答QWQ
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=31;
int l,r;
LL f[N][2],g[N][2],c[N][N];
void init(){
for(int i=0;i<N;i++){
for(int j=0;j<=i;j++){
if(j)c[i][j]=c[i-1][j-1]+c[i-1][j];
else c[i][j]=1;
f[i][j&1]+=c[i][j];
}
}
for(int i=1;i<N;i++){
g[i][0]=f[i-1][1]*(1<<(i-1))+g[i-1][0]+g[i-1][1];
g[i][1]=f[i-1][0]*(1<<(i-1))+g[i-1][1]+g[i-1][0];
}
}
LL count(int x,int op){
if(x==0){
return f[x][op];
}
int idx=0;
for(int i=30;i>=0;i--){
if((x>>i)&1){
idx=i;
break;
}
}
LL p=(1<<idx);
return f[idx][op]+count(x-p,op^1);
}
LL solve(int x,int op){
// cout<<x<<"\n";
LL res=0;
int idx=-1;
for(int i=30;i>=0;i--){
if((x>>i)&1){
idx=i;
break;
}
}
if(idx==-1){
return 0;
}
LL p=(1<<idx);
res=g[idx][op]+p*count(x-p,op^1)+solve(x-p,op^1);
return res;
}
int main(){
init();
cin>>l>>r;
cout<<solve(r,1)-solve(l-1,1);//1 奇數 0 偶數
return 0;
}

浙公網安備 33010602011771號