1026: [SCOI2009]windy数
2021-03-31 11:27
阅读:584
【数据规模和约定】
100%的数据,满足 1
windy数的大致意思是:像135,6913,13579,这样每两个相邻数字的差≥2
数位dp:
正面直接猜想,保存2000000000状态无疑是不可能的,必须采用更加巧妙的方法。
可以设dp数组为:f[i][j],i表示数字位数,j表示最高位的数字
因此可以得到dp方程:
\[f[i][j]=\sum_{k=0}^{k\leq 9} f[i-1][k]\left (\left | k-j \right |\geq 2\right )\]
但这只计算出最高位为j的结果,无法求出范围内的结果,这时可以转换思想,求出1~b的结果减去1~a-1的结果,不就是答案了吗?
设len表示数字位数,T[i]表示第i位的数字
首先,ans加上1~len-1位的情况
然后ans加上最高位数字为1~T[len]-1的情况
接着以此类推,加上次最高位1~T[len-1]-1的情况,加上次次最高位1~T[len-2]-1的情况。。。。。。
1 #include2 #include 3 #include 4 #include 5 using namespace std; 6 7 #define LL long long 8 9 int a,b; 10 LL f[20][10]; 11 12 LL solve(int t) 13 { 14 LL ans=0; 15 int len=0,T[20]; 16 while(t) 17 { 18 T[++len]=t%10; 19 t/=10; 20 } 21 for(int i=1;i ) 22 for(int j=1;j9;j++) 23 ans+=f[i][j]; 24 for(int i=1;i ) 25 ans+=f[len][i]; 26 for(int i=len-1;i>=1;i--) 27 { 28 for(int j=0;j ) 29 if(abs(j-T[i+1])>=2) 30 ans+=f[i][j]; 31 if(abs(T[i]-T[i+1])2) break; 32 } 33 return ans; 34 } 35 36 int main() 37 { 38 scanf("%d %d",&a,&b); 39 for(int i=0;i9;i++) f[1][i]=1; 40 for(int i=2;i15;i++) 41 for(int j=0;j9;j++) 42 for(int k=0;k9;k++) 43 if(abs(k-j)>=2) 44 f[i][j]+=f[i-1][k]; 45 cout1)-solve(a)endl; 46 return 0; 47 }
上一篇:win10安装VMware v14.1.1.28517
下一篇:新股日历数据API
文章来自:搜素材网的编程语言模块,转载请注明文章出处。
文章标题:1026: [SCOI2009]windy数
文章链接:http://soscw.com/index.php/essay/70443.html
文章标题:1026: [SCOI2009]windy数
文章链接:http://soscw.com/index.php/essay/70443.html
评论
亲,登录后才可以留言!