数位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 ...
随机推荐
- 安装cocoa pods时出现Operation not permitted - /usr/bin/xcodeproj的问题
安装cocoa pods时, 在命令行中输入: 安装:sudo gem install cocoapods报Operation not permitted - /usr/bin/xcodeproj这个 ...
- 深入理解java虚拟机_前言
2.JVM虚拟机 2.1 概述 java获得广泛认可主要是因为: (1) java是一门结构严谨.面向对象的编程语言; (2) java摆脱了硬件平台的束缚,实现了“一次编写,到处运行”的理想; ...
- java中的参数传递是按引用传递还是按值传递
最近去面试,有一个面试官问到java中参数传递的问题,感觉自己对于这一块还是理解的不够深.今天我们就一起来学习一下Java中的接口和抽象类.下面是本文的目录大纲: 一 . 什么是按值传递,什么是按引用 ...
- AO之Addins开发[杂谈1] Toolbar中添加一条分割线
在XML代码中,给Item添加separator属性,需要从哪里打分割线,就将其设置为true即可.如下图所示: 如紫色框住的灰色竖线所示. 默认separator属性是false的,这个小东西极其隐 ...
- Overlapping rectangles判断两个矩形是否重叠的问题 C++
Given two rectangles, find if the given two rectangles overlap or not. A rectangle is denoted by pro ...
- Java之路第一步——第一行Java代码
main()方法是Java应用程序的入口方法,也就是说,程序在运行的时候,第一个执行的方法就是main()方法. 名字必须是main: 必须是public static void 类型的: 必须接收一 ...
- MySQL5.6中date和string的转换和比较
Conversion & Comparison, involving strings and dates in MySQL 5.6 我们有张表,表中有一个字段dpt_date,SQL类型为da ...
- angularjs 字段排序 多字段排序
我们用angularjs {{}},ng-model循环绑定数组或对象的内容的时候,有时候会用到排序,有时候可能会有多个字段排序 具体要用到过滤 数据的展现,可以通过ng-repeat实现.当网页解析 ...
- Python第二十二天 stat模块 os.chmod方法 os.stat方法 pwd grp模块
Python第二十二天 stat模块 os.chmod方法 os.stat方法 pwd grp模块 stat模块描述了os.stat(filename)返回的文件属性列表中各值的意义,根据 ...
- JavaScript Array 对象方法 以及 如何区分javascript中的toString()、toLocaleString()、valueOf()方法
1.concat() 2.join() 3.pop() 4.push() 5.reverse() 6.shift() 7.unshift() 8.slice() 9.sort() 10.splice( ...