数位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 ...
随机推荐
- SpringMVC处理multipart请求.
一.简述 multipart格式的数据会将一个表单拆分为多个部分(part),每个部分对应一个输入域.在一般的表单输入域中,它所对应的部分中会放置文本型数据,但是如果上传文件的话,它所对应的部分可以是 ...
- 使用JavaScript将图片保存至本地
在最近的开发当中,我们需要为img标签以及canvas动态绘制的图像提供下载功能,下面是经过探索后我们得出的结果. 一.Canvas 版本 // 下载Canvas元素的图片 function down ...
- Spring基础篇——Spring容器和应用上下文理解
上文说到,有了Spring之后,通过依赖注入的方式,我们的业务代码不用自己管理关联对象的生命周期.业务代码只需要按照业务本身的流程,走啊走啊,走到哪里,需要另外的对象来协助了,就给Spring说,我想 ...
- Nodejs密集型CPU解决方案
首先说一下nodejs单线程的优势: 高性能,与php相比,避免了频繁创建切换线程的开销,执行更加迅速,资源占用小. 线程安全,不用担心同一变量被多线程读写,造成程序崩溃. 单线程的异步和非阻塞,其实 ...
- unity创建和加载AssetBundle
先说一下为什么要使用AssetBundle吧,以前做东西一直忽略这个问题,现在认为这个步骤很重要,代码是次要的,决策和为什么这样搞才是关键. 一句话概括吧,AssetBundle实现了资源与服务分离, ...
- 从MongoDB的ObjectId中获取时间信息
MongoDB默认使用_id字段作为主键,类型为ObjectId.ObjectId的生成有一定的规则,详情可以查看这篇文章 - MongoDB深究之ObjectId.如果你在写入数据库的时候忘记写入创 ...
- python基础(三)编码,深浅copy
编码,深浅copy encode,decode在python2中使用的一些迷糊,python3中更容易理解 要理解encode和decode,首先我们要明白编码,字符和二进制的相关概念,简单来说,计算 ...
- Android 根据字符串动态获取资源ID
1.常用方法public int getResId(String name,Context context){ Resources r = context.getResources(); int id ...
- 关于t00ls的挂机脚本
0x00 前言 今天早上发现t00ls上有人发了个挂机脚本,二十四小时刷时间以及刷Tubi. 轻轻松松升级,坐收Tubi成富翁. 代码很简单,就是带上cookie每隔一段时间(比如60秒)去请求一下某 ...
- Python 调用让系统自动调用默认程序打开文件?
windows上可以使用os.startfile os.startfile(file) linux上可以使用xdg-open subprocess.call(["xdg-open" ...