数位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 ...
随机推荐
- iOS动态性 运行时runtime初探(强制获取并修改私有变量,强制增加及修改私有方法等)
借助前辈的力量综合一下资料. OC是运行时语言,只有在程序运行时,才会去确定对象的类型,并调用类与对象相应的方法.利用runtime机制让我们可以在程序运行时动态修改类.对象中的所有属性.方法,就算是 ...
- 查看内存和cpu
top: 主要参数 d:指定更新的间隔,以秒计算. q:没有任何延迟的更新.如果使用者有超级用户,则top命令将会以最高的优先序执行. c:显示进程完整的路径与名称. S:累积模式,会将己完成或消失的 ...
- rm 命令详解
rm 作用: 删除一个目录中的一个或多个文件或目录,也可以将某个目录及下属的所有文件及子目录均删除掉, 对于连接文件只是删除整个连接文件,而保持原有文件. 注意: 使用rm 命令要格外小心,因为一旦 ...
- which 命令详解
一.which 作用: which 命令用于查找并显示给定命令的绝对路径,环境变量PATH中保存了查找命令时需要遍历的目录, which 命令会在环境变量$PATH 设置的目录里查找符合条件的文件.也 ...
- Ubuntu配置Django+ Apache2+ mysql
# 我的Ubuntu上自带的python3.5,所以安装一下 python3.6sudo add-apt-repository ppa:jonathonf/python-3.6sudo apt-get ...
- 2.移植uboot-添加2440单板,并实现NOR、NAND启动
上章分析了uboot启动流程后,接下来便来配置新的单板,实现nor.nand启动 1.首先在uboot里新建单板2440 : cd board/samsung/ cp smdk2410 smdk244 ...
- centos7 部署dns服务器
=============================================== 2017/12/6_第2次修改 ccb_warlock 20 ...
- 【转】java jvm 线程 与操作系统线程
原文链接:http://segmentfault.com/q/1010000000370403 Java的目标是要跨平台,而不同的操作系统(如类Unix和Windows)其任务调度机制有很大的不同,故 ...
- java RTTI笔记 之Class学习笔记(摘自java编程思想)
1.java 使用Class对象来执行其RTTI.java 中每个类在编译后都会对应产生一个Class对象(更恰当地说是被保存在一个同名的.class文件中),甚至void和基本类型也都对应一个cla ...
- bootstrap 导航栏鼠标悬停显示下拉菜单
在jsp中加入一下代码: .navbar .nav > li:hover .dropdown-menu { display: block;} 全部代码如下所示: <%@ page lang ...