Gym - 102040B Counting Inversion (数位dp)
题意:求[a,b]区间内的数字中正序对的个数。
具体思路参考:
https://blog.csdn.net/weixin_43135318/article/details/88061396
https://www.cnblogs.com/asdfsag/p/11278519.html
在此基础上维护一下每个状态中大于每个数字的数字出现的次数即可。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const ll N=20; 5 ll bit[N],nbit,f[N][2][2],g[N][2][2][N],G[N][2][2],vis[N][2][2],ka,a,b,ka2; 6 void dfs(ll u,ll ze,ll lim) { 7 if(vis[u][ze][lim]==ka)return; 8 vis[u][ze][lim]=ka; 9 G[u][ze][lim]=0; 10 for(ll i=0; i<=9; ++i)g[u][ze][lim][i]=0; 11 if(u==0) {f[u][ze][lim]=1; return;} 12 f[u][ze][lim]=0; 13 for(ll i=0; i<=(lim?bit[u]:9); ++i) { 14 ll v=u-1,ze2=ze&&i==0,lim2=lim&&i==bit[u]; 15 dfs(v,ze2,lim2); 16 f[u][ze][lim]+=f[v][ze2][lim2]; 17 for(ll j=0; j<=9; ++j)g[u][ze][lim][j]+=g[v][ze2][lim2][j]; 18 G[u][ze][lim]+=G[v][ze2][lim2]; 19 if(!ze2) { 20 for(ll j=0; j<=i; ++j)g[u][ze][lim][j]+=f[v][ze2][lim2]; 21 G[u][ze][lim]+=g[v][ze2][lim2][i+1]; 22 } 23 } 24 } 25 ll solve(ll x) { 26 ++ka; 27 for(nbit=0; x; x/=10)bit[++nbit]=x%10; 28 dfs(nbit,1,1); 29 return G[nbit][1][1]; 30 } 31 int main() { 32 ll T; 33 for(scanf("%lld",&T); T--;) { 34 scanf("%lld%lld",&a,&b); 35 printf("Case %lld: %lld\n",++ka2,solve(b)-solve(a-1)); 36 } 37 }