数位dp初探
我这种蒟蒻就一直不会写数位dp。。
于是开了个坑。。
1833: [ZJOI2010]count 数字计数
这道被KPM大爷说是入门题。。嗯似乎找找规律然后减掉0的情况后乱搞就可以了。。(但是还是写了很久TAT
#include<cstring>
#include<iostream>
#include<cstdio>
#include<queue>
#include<cmath>
#include<algorithm>
#define rep(i,l,r) for (int i=l;i<=r;i++)
#define down(i,l,r) for (int i=l;i>=r;i--)
#define clr(x,y) memset(x,y,sizeof(x))
#define low(x) (x&(-x))
#define maxn 505
#define inf int(1e9)
#define mm 1000000007
#define ll long long
using namespace std;
ll ans[][];
ll a,b,bin[];
ll read(){
ll x=,f=; char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-; ch=getchar();}
while (isdigit(ch)) {x=x*+ch-''; ch=getchar();}
return x*f;
}
int get(ll x){
if (x==) return ;
int ans=;
while(x){ans++; x/=;}
return ans;
}
void cal(ll x,int f){
int L,l=get(x),a; L=l;
rep(i,,) ans[i][f]=(l-)*bin[l-];
rep(i,,l-) ans[][f]-=bin[i];
while (l){
a=x/bin[l-];
if (l==L) rep(i,,a-) {
ans[i][f]+=bin[l-];
if (l->=) rep(j,,) ans[j][f]+=1LL*(l-)*bin[l-];
}
if (l!=L) rep(i,,a-) {
ans[i][f]+=bin[l-];
if (l->=) rep(j,,) ans[j][f]+=1LL*(l-)*bin[l-];
}
ans[a][f]+=x%bin[l-]+;
x=x%bin[l-];
l--;
}
}
int main(){
bin[]=; rep(i,,) bin[i]=bin[i-]*;
a=read(); b=read();
cal(a-,);
cal(b,);
rep(i,,) printf("%lld ",ans[i][]-ans[i][]);
printf("%lld\n",ans[][]-ans[][]);
return ;
}
1026: [SCOI2009]windy数
这道写个dp f[i][j]表示第i位最前一位数是j,特判一下0的情况。。
#include<cstring>
#include<iostream>
#include<cstdio>
#include<queue>
#include<cmath>
#include<algorithm>
#define rep(i,l,r) for (int i=l;i<=r;i++)
#define down(i,l,r) for (int i=l;i>=r;i--)
#define clr(x,y) memset(x,y,sizeof(x))
#define low(x) (x&(-x))
#define maxn 505
#define inf int(1e9)
#define mm 1000000007
#define ll long long
using namespace std;
int f[][],bin[];
int a,b;
int read(){
int x=,f=; char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-; ch=getchar();}
while (isdigit(ch)) {x=x*+ch-''; ch=getchar();}
return x*f;
}
int get(ll x){
if (x==) return ;
int ans=;
while(x){ans++; x/=;}
return ans;
}
int cal(int x){
int L,l=get(x),ans=,a,tmp=-; L=l;
if (l>) ans++;//0的情况
rep(i,,l-) {
rep(j,,) ans+=f[i][j];
}
while (l){
a=x/bin[l-];
if (l==L) rep(i,,a-) if (abs(i-tmp)>=){
rep(j,,) if (abs(i-j)>=) ans+=f[l-][j];
}
if (l!=L) rep(i,,a-) if (abs(i-tmp)>=){
rep(j,,) if (abs(i-j)>=) ans+=f[l-][j];
}
if (l==) rep(i,,a) if (abs(tmp-i)>=) ans++;
if (abs(tmp-a)<) break;
tmp=a;
x%=bin[l-];
l--;
}
return ans;
}
int main(){
bin[]=; rep(i,,) bin[i]=bin[i-]*;
a=read(); b=read();
int l=get(b);
rep(i,,) f[][i]=;
rep(i,,) rep(j,,) if (f[i][j]){
rep(k,,) if (abs(j-k)>=) f[i+][k]+=f[i][j];
}
printf("%d\n",cal(b)-cal(a-));
return ;
}
1072: [SCOI2007]排列perm
为什么我一直认为这道是状压。。 f[s][i]表示当前状态是s,模数为i。然后枚举每一个数是否被选过转移就可以了。
最后除掉相同数字个数的阶乘。
#include<cstring>
#include<iostream>
#include<cstdio>
#include<queue>
#include<cmath>
#include<algorithm>
#define rep(i,l,r) for (int i=l;i<=r;i++)
#define down(i,l,r) for (int i=l;i>=r;i--)
#define clr(x,y) memset(x,y,sizeof(x))
#define low(x) (x&(-x))
#define maxn 505
#define inf int(1e9)
#define mm 1000000007
#define ll long long
using namespace std;
int f[][];
int n,t,l,bin[],a[],num[],p[],ans;
char s[];
int read(){
int x=,f=; char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-; ch=getchar();}
while (isdigit(ch)) {x=x*+ch-''; ch=getchar();}
return x*f;
}
int main(){
t=read();
bin[]=; rep(i,,) bin[i]=bin[i-]*;
p[]=; rep(i,,) p[i]=p[i-]*i;
while (t--){
clr(f,); clr(num,);
scanf("%s",s); l=strlen(s);
int d=read();
rep(i,,l-) a[i]=s[i]-'',num[a[i]]++;
//printf("%d\n",bin[l]-1);
f[][]=;
rep(s,,bin[l]-) rep(j,,d-) if (f[s][j]){
rep(k,,l-) if ((s&bin[k])==) f[s+bin[k]][(j*+a[k])%d]+=f[s][j];
}
ans=f[bin[l]-][];
rep(i,,) if (num[i]) ans/=p[num[i]];
printf("%d\n",ans);
}
return ;
}
2425: [HAOI2010]计数
题目其实就是给你一些数字让你用这些数字构造一个个比给定数小的数。。
比如说我现在这一位最高为x,那就取0~x-1(可以有前导0)为这一位然后剩下的数自由组合。
对于这个自由组合,比如剩下有n位,这个数字还剩下有x个,那每一次就乘上C(n,x)然后n-=x。
#include<cstring>
#include<iostream>
#include<cstdio>
#include<queue>
#include<cmath>
#include<algorithm>
#define rep(i,l,r) for (int i=l;i<=r;i++)
#define down(i,l,r) for (int i=l;i>=r;i--)
#define clr(x,y) memset(x,y,sizeof(x))
#define low(x) (x&(-x))
#define maxn 505
#define inf int(1e9)
#define mm 1000000007
#define ll long long
using namespace std;
ll c[][],ans;
int cnt[],a[];
char s[];
int read(){
int x=,f=; char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-; ch=getchar();}
while (isdigit(ch)) {x=x*+ch-''; ch=getchar();}
return x*f;
}
ll cal(int n){
ll ans=;
int now=n;
rep(i,,) ans*=c[now][cnt[i]],now-=cnt[i];
return ans;
}
int main(){
c[][]=;
rep(i,,) {
c[i][]=;
rep(j,,) c[i][j]=c[i-][j-]+c[i-][j];
}
scanf("%s",s); int l=strlen(s);
rep(i,,l-) a[i+]=s[i]-'',cnt[a[i+]]++;
rep(i,,l) {
rep(j,,a[i]-) if (cnt[j]){
cnt[j]--;
ans+=cal(l-i);
cnt[j]++;
}
cnt[a[i]]--;
}
printf("%lld\n",ans);
return ;
}
BZOJ1799: [Ahoi2009]self 同类分布
http://www.cnblogs.com/ctlchild/p/5126952.html
(还有几道题目慢慢填TAT。。。
数位dp初探的更多相关文章
- 初探数位dp
数位dp有着很明显的特点,一般来说是给定区间[l,r]求满足某种条件区间中的数有多少个 朴素解法一般是O(n)的而n往往很大(10^8起步) 这时候我们就要想办法优化,于是就有了数位dp 数位有两个基 ...
- 数位类统计问题--数位DP
有一类与数位有关的区间统计问题.这类问题往往具有比较浓厚的数学味道,无法暴力求解,需要在数位上进行递推等操作.这类问题往往需要一些预处理,这就用到了数位DP. 本文地址:http://www.cnbl ...
- 数位dp入门 hdu2089 不要62
数位dp入门 hdu2089 不要62 题意: 给定一个区间[n,m] (0< n ≤ m<1000000),找出不含4和'62'的数的个数 (ps:开始以为直接暴力可以..貌似可以,但是 ...
- 动态规划——数位dp
通过先前在<动态规划——背包问题>中关于动态规划的初探,我们其实可以看到,动态规划其实不是像凸包.扩展欧几里得等是具体的算法,而是一种在解决问题中决策的思想.在不同的题目中,我们都需要根据 ...
- [bzoj1833][ZJOI2010]count 数字计数——数位dp
题目: (传送门)[http://www.lydsy.com/JudgeOnline/problem.php?id=1833] 题解: 第一次接触数位dp,真的是恶心. 首先翻阅了很多很多一维dp,因 ...
- 【BZOJ1662】[Usaco2006 Nov]Round Numbers 圆环数 数位DP
[BZOJ1662][Usaco2006 Nov]Round Numbers 圆环数 Description 正如你所知,奶牛们没有手指以至于不能玩"石头剪刀布"来任意地决定例如谁 ...
- bzoj1026数位dp
基础的数位dp 但是ce了一发,(abs难道不是cmath里的吗?改成bits/stdc++.h就过了) #include <bits/stdc++.h> using namespace ...
- uva12063数位dp
辣鸡军训毁我青春!!! 因为在军训,导致很长时间都只能看书yy题目,而不能溜到机房鏼题 于是在猫大的帮助下我发现这道习题是数位dp 然后想起之前讲dp的时候一直在补作业所以没怎么写,然后就试了试 果然 ...
- HDU2089 不要62[数位DP]
不要62 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
随机推荐
- Python的HTTP服务实例
1.前言 今天需要实现一个Pyhton的http服务,与Web的JS进行交换. 2.实例代码 支持HEAD.GET.POST方法,将参数转换为JSON格式,返回结果以JSON字符串返回. import ...
- ArcGIS 网络分析[1.3] 在个人地理数据库中创建网络数据集/并简单试验最佳路径
上篇使用shp文件创建网络数据集,然而在ArcGIS 9中就支持地理数据库了,数据库的管理更为科学强大. 本篇就使用个人地理数据库进行建立网络数据集,线数据仍然可以是1.1中的线数据,但是我做了一些修 ...
- ArcGIS API for JavaScript 4.2学习笔记[16] 弹窗自定义功能按钮及为要素自定义按钮(第五章完结)
这节对Popups这一章的最后两个例子进行介绍和解析. 第一个[Popup Actions]介绍了弹窗中如何自定义工具按钮(名为actions),以PopupTemplate+FeatureLayer ...
- 程序员的自我救赎---11.4:FileSystem文件服务
<前言> (一) Winner2.0 框架基础分析 (二)PLSQL报表系统 (三)SSO单点登录 (四) 短信中心与消息中心 (五)钱包系统 (六)GPU支付中心 (七)权限系统 (八) ...
- java-FFmpeg(一) 实现视频的转码和截图功能
FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用LGPL或GPL许可证(依据你选择的组件).它提供了录制.转换以及流化音视频的完整解决方案.它包含了非常先进的音频/视频编解码库l ...
- DES加解密、JavaScript、Java
JavaScript代码 DES.js /** * Created by Andy on 2017/11/30. */ /** * DES加密/解密 * @Copyright Copyright ...
- Android中菜单图标等系统自带的图标
Android™ 2.1 android.R.drawable Icon Resources Android™ 1.5 android.R.drawable Icon Resources Androi ...
- Sql Server 里的向上取整、向下取整、四舍五入取整的实例!
http://blog.csdn.net/dxnn520/article/details/8454132 =============================================== ...
- iOS学习——UI相关小结
1 StoryBoard: 在Info.plist中可以查看Main storyboard,即入口storyboard,默认为main.storyboard,可以修改为自己创建的storybo ...
- Java求循环节长度
两个整数做除法,有时会产生循环小数,其循环部分称为:循环节.比如,11/13=6=>0.846153846153..... 其循环节为[846153] 共有6位.下面的方法,可以求出循环节的长 ...