【数位dp】
hdu5787
问:L ~ R有多少个数是K-wolf Number?其中,K-wolf Number的定义是这个数在十进制下,任意相邻的K个字符没有相同的。
dp[i][j][k]表示有i个空位可填,其中不能填j这个数字中所含有的字符,k = true(表示j有前导0)时,还不能填0.
#include <bits/stdc++.h>
#define ll long long
#define pii pair<int, int>
#define mp make_pair
#define fi first
#define se second
using namespace std;
const int N = 1e5+;
ll l, r;
int k;
ll dp[][][];
int temp[], tot; ll dfs(int pos, int w, bool tag, bool flag){ if(!pos) return ;
if(flag&&~dp[pos][w][tag]) return dp[pos][w][tag];
int Max = flag? : temp[pos]; int ret[], sum = , tmp = w;
while(tmp)
ret[sum++] = tmp%, tmp /= ;
if(tag) ret[sum++] = ; ll ans = ;
for(int i = ; i <= Max; i++){
bool tag2 = true;
for(int j = ; j < sum&&j < k-; j++)
if(ret[j] == i) tag2 = false;
if(tag2){
tmp = ;
int first = min(k-, sum-);
for(int j = first; j >= ; j--)
tmp = tmp*+ret[j];
bool tag3 = false;
if(first >= &&ret[first] == ) tag3 = true;
ans += dfs(pos-, tmp*+i, tag3, flag||i != Max);
}
}
if(flag) dp[pos][w][tag] = ans;
//printf("dfs %d, %d, %d, %d %lld\n", pos, w, tag*1, flag*1, ans);
return ans;
} ll solve(ll x){
tot = ;
while(x){
temp[++tot] = x%;
x /= ;
}
return dfs(tot, , , );
}
int main(){
while(cin >> l >> r >> k){
memset(dp, -, sizeof(dp));
ll ans = solve(r)-solve(l-);
cout << ans << endl;
}
return ;
}
hdu3652
问:1~n有多少个数含有连续的“13”并且能被13整除。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int dp[][][][];
int temp[], tot; int dfs(int pos, int mod, int pre, bool tag13, bool flag){
if(!pos)
return (mod == &&tag13);
if(flag&&~dp[pos][mod][pre][tag13]) return dp[pos][mod][pre][tag13];
int Max = flag? : temp[pos]; int ans = ;
for(int i = ; i <= Max; i++)
ans += dfs(pos-, (mod*+i)%, i, tag13||(pre == &&i == ), flag||i != Max);
if(flag) dp[pos][mod][pre][tag13] = ans;
return ans;
} int solve(int x){
tot = ;
while(x){
temp[++tot] = x%;
x /= ;
}
return dfs(tot, , , , );
}
int main(){
memset(dp, -, sizeof(dp));
int n;
while(cin >> n){
ll ans = solve(n)-solve();
cout << ans << endl;
}
return ;
}
hdu4734
问:0~B中有多少数字各个数位权值和小于 f(A).
#include <bits/stdc++.h>
using namespace std;
int lim;
int dp[][<<];
int temp[], tot;
int dfs(int pos, int sum, bool flag){
if(!pos)
return ;
if(flag&&~dp[pos][sum]) return dp[pos][sum];
int Max = flag? : temp[pos];
int ans = ;
for(int i = ; i <= Max; i++){
if( (i<<(pos-)) <= sum )
ans += dfs(pos-, sum-(i << (pos-)), flag||i != Max);
}
if(flag) dp[pos][sum] = ans;
return ans;
} int solve(int x){
tot = ;
while(x){
temp[++tot] = x%;
x /= ;
}
return dfs(tot, lim, );
}
int main(){
memset(dp, -, sizeof(dp));
int t, a, b, ca = ; scanf("%d", &t);
while(t--){
scanf("%d%d", &a, &b);
lim = ;
for(int i = ; a; i++){
lim += (a%)<<i;
a /= ;
}
// lim < (9*2^9)
int ans = solve(b)-solve()+;
printf("Case #%d: %d\n", ca++, ans);
}
return ;
}
hdu4507
问:l~r中与7无关的数的平方和。与7无关的数定义为:不含数字7,不是7的倍数,且各位数和不是7的倍数。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int P = 1e9+;
ll f[];
ll l, r;
struct p{
ll x, y, z;
p(){}
p(ll x, ll y, ll z):x(x), y(y), z(z){}
};
p dp[][][];
int temp[], tot;
void ad(ll& a, ll b){
a += b;
if(a < ) a = a%P+P;
if(a >= P) a %= P;
}
p dfs(int pos, int add, int mod, bool flag){
if(!pos)
return p(add&&mod, , );
if(flag&&dp[pos][add][mod].x != -) return dp[pos][add][mod]; int Max = flag? : temp[pos];
ll ans = , sum = , sum2 = ;
for(int i = ; i <= Max; i++) if(i != ){
p ret = dfs(pos-, (add+i)%, (mod*+i)%, flag||i != Max);
//i*10^(pos-1)+x
ll tmp = f[pos-]*i%P;
ans += ret.x;
ad(sum, (ret.y+ret.x%P*tmp)%P);
ad(sum2, (ret.x%P*tmp%P*tmp%P+*tmp*ret.y%P+ret.z)%P);
}
if(flag) dp[pos][add][mod] = p(ans, sum, sum2);
//printf("pos %d, add %d, mod %d, flag %d: %lld %lld %lld\n", pos, add, mod, flag*1, ans, sum, sum2);
return p(ans, sum, sum2);
} ll solve(ll x){
tot = ;
while(x){
temp[++tot] = x%;
x /= ;
}
return dfs(tot, , , ).z;
}
int main(){
f[] = ;
for(int i = ; i <= ; i++) f[i] = f[i-]*%P;
memset(dp, -, sizeof(dp));
int t, a, b, ca = ; scanf("%d", &t);
while(t--){
scanf("%lld%lld", &l, &r);
ll ans = solve(r)-solve(l-);
ans %= P;
if(ans < ) ans += P;
printf("%lld\n", ans);
}
return ;
}
hdu3709
问:l~r中有多少数字是平衡数? 平衡数的定义为能在数字中找到某一个点作为支点使左边的力矩和右边的力矩相等?如4139,以3为支点时左边是4*2+1*1 = 9, 右边是9*1 = 9.
#include <bits/stdc++.h>
#define ll unsigned long long
using namespace std;
ll dp[][][+];
ll l, r; int temp[], tot; ll dfs(int pos, bool pre, int pivot, int now, bool flag){
if(!pos)
return now == ;
if(flag&&~dp[pos][pivot][+now]) return dp[pos][pivot][+now]; int Max = flag? : temp[pos];
ll ans = ;
for(int i = ; i <= Max; i++){
if(!pre&&pivot == pos&&!i) continue ;
int ret = now+(pos-pivot)*i;
if(ret > ||ret < -) continue ;
ans += dfs(pos-, pre||i, pivot, ret, flag||i != Max);
} if(flag) dp[pos][pivot][+now] = ans;
return ans;
} ll solve(ll x){
tot = ;
while(x){
temp[++tot] = x%;
x /= ;
}
ll ans = ;
for(int i = ; i <= tot; i++)
ans += dfs(tot, , i, , );
return ans;
}
int main(){
memset(dp, -, sizeof(dp));
int t, ca = ; scanf("%d", &t);
while(t--){
cin >> l >> r;
ll ans = ;
if(l == ) l++, ans++;
ans += solve(r)-solve(l-);
cout << ans << endl;
}
return ;
}
SPOJ Balanced Numbers
问:l~r有多少数字满足奇数数字出现偶数次偶数数字出现奇数次。
#include <bits/stdc++.h>
#define ll unsigned long long
using namespace std;
//3^10 = 59049
ll f[];
ll dp[][][];
ll l, r; int temp[], tot;
bool judge(int x){
bool tag = true;
while(x){
int ret = x%;
if(ret){
ret &= ;
if(ret != tag) return false;
}
tag = !tag;
x /= ;
}
return true;
}
ll dfs(int pos, bool pre, int now, bool flag){//pre == true 1
// printf("%d %d %d %d\n", pos, pre*1, now, flag*1);
if(!pos)
return judge(now);
if(flag&&~dp[pos][pre][now]) return dp[pos][pre][now]; int Max = flag? : temp[pos];
ll ans = ;
for(int i = ; i <= Max; i++){
int ret = ;//3^j
if(i||pre){
ret = (now/f[i])%;
if(ret < ) ret = now+f[i];
else ret = now-f[i];
}
ans += dfs(pos-, pre||i, ret, flag||i != Max);
} if(flag) dp[pos][pre][now] = ans;
//printf("pos %d, add %d, mod %d, flag %d: %lld %lld %lld\n", pos, add, mod, flag*1, ans, sum, sum2);
return ans;
} ll solve(ll x){
tot = ;
while(x){
temp[++tot] = x%;
x /= ;
}
return dfs(tot, , , );
}
int main(){
f[] = ;
for(int i = ; i < ; i++) f[i] = f[i-]*;
memset(dp, -, sizeof(dp));
int t, ca = ; scanf("%d", &t);
while(t--){
cin >> l >> r;
ll ans = solve(r)-solve(l-);
cout << ans << endl;
}
return ;
}
hdu4352
问:l~r有多少数字的严格最长上升子序列是k?
题解:状压。dp[还剩i位][k][二进制位下的最长上升子序列]
#include <bits/stdc++.h>
#define ll unsigned long long
using namespace std;
const int N = 1e5+;
const int P = 1e9+;
ll dp[][][<<];
ll l, r, k; int temp[], tot;
ll dfs(int pos, int k, int now, bool flag){
if(!pos)
return __builtin_popcount(now) == k;
if(flag&&~dp[k][pos][now]) return dp[k][pos][now]; int Max = flag? : temp[pos];
ll ans = ;
for(int i = ; i <= Max; i++) {
if(!now&&!i) {
ans += dfs(pos-, k, now, flag||i != Max);
continue ;
}
int ret = now;
if( !((ret>>i)&) ){//ret[i] : 0
if( ret>>i ){
for(int j = i+; j; j++)
if((ret>>j)&){
ret ^= <<j;
break;
}
}
ret |= <<i;
}
ans += dfs(pos-, k, ret, flag||i != Max);
} if(flag) dp[k][pos][now] = ans;
return ans;
} ll solve(ll x){
tot = ;
while(x){
temp[++tot] = x%;
x /= ;
}
return dfs(tot, k, , );
}
int main(){
memset(dp, -, sizeof(dp)); int t, ca = ; scanf("%d", &t);
while(t--){
cin >> l >> r >> k;
ll ans = solve(r)-solve(l-);
printf("Case #%d: ", ca++);
cout << ans << endl;
}
return ;
}
Codeforces 55D
问:l~r有多少数字可以被各个位上的非0数字整除?
#include <bits/stdc++.h>
#define ll unsigned long long
using namespace std;
const int P = ;
ll dp[][<<][];
ll l, r;
int w[][] = {
{, , , },
{, , , },
{, , , },
{, , , },
{, , , },
{, , , },
{, , , },
{, , , },
{, , , },
{, , , }
};
int temp[], tot;
ll dfs(int pos, int k, int now, bool flag){
//printf("%d %d %d\n", pos, k, now);
if(!pos){
int a2 = k&, a3 = (k>>)&, a5 = (k>>)&, a7 = k>>;
if(a2 == &&now%) return ;
if(a2 == &&now%) return ;
if(a2 == &&now%) return ;
if(a3 == &&now%) return ;
if(a3 == &&now%) return ;
if(a5&&now%) return ;
if(a7&&now%) return ;
return ;
}
if(flag&&~dp[pos][k][now]) return dp[pos][k][now]; int Max = flag? : temp[pos];
ll ans = ;
int ret[], ret2[];
ret[] = k&, ret[] = (k>>)&, ret[] = (k>>)&, ret[] = k>>;
for(int i = ; i <= Max; i++) {
for(int j = ; j < ; j++)
ret2[j] = max(ret[j], w[i][j]);
int r = ret2[]+(ret2[]<<)+(ret2[]<<)+(ret2[]<<);
ans += dfs(pos-, r, (now*+i)%, flag||i != Max);
} if(flag) dp[pos][k][now] = ans;
//printf("%d %d %d: %lld\n", pos, k, now, ans);
return ans;
} ll solve(ll x){
tot = ;
while(x){
temp[++tot] = x%;
x /= ;
}
return dfs(tot, , , );
}
int main(){
memset(dp, -, sizeof(dp));
int t, ca = ; scanf("%d", &t);
while(t--){
cin >> l >> r;
ll ans = solve(r)-solve(l-);
cout << ans << endl;
}
return ;
}
【数位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 ...
- 数位DP GYM 100827 E Hill Number
题目链接 题意:判断小于n的数字中,数位从高到低成上升再下降的趋势的数字的个数 分析:简单的数位DP,保存前一位的数字,注意临界点的处理,都是套路. #include <bits/stdc++. ...
- 数位dp总结
由简单到稍微难点. 从网上搜了10到数位dp的题目,有几道还是很难想到的,前几道基本都是模板题,供入门用. 点开即可看题解. hdu3555 Bomb hdu3652 B-number hdu2089 ...
- 数位DP入门
HDU 2089 不要62 DESC: 问l, r范围内的没有4和相邻62的数有多少个. #include <stdio.h> #include <string.h> #inc ...
- 数位DP之奥义
恩是的没错数位DP的奥义就是一个简练的dfs模板 int dfs(int position, int condition, bool boundary) { ) return (condition ? ...
- 浅谈数位DP
在了解数位dp之前,先来看一个问题: 例1.求a~b中不包含49的数的个数. 0 < a.b < 2*10^9 注意到n的数据范围非常大,暴力求解是不可能的,考虑dp,如果直接记录下数字, ...
- 数位DP
题意:(hdu 4734) 我们定义十进制数x的权值为f(x) = a(n)*2^(n-1)+a(n-1)*2(n-2)+...a(2)*2+a(1)*1,a(i)表示十进制数x中第i位的数字. 题目 ...
随机推荐
- 查留言总人数的sql语句
select count(distinct user_id) from bidproduct
- Shell displays color output
格式: echo "/033[字背景颜色;字体颜色m字符串/033[控制码" 如果单纯显示字体颜色可以固定控制码位0m. 格式: echo "/033[字背景颜色;字体颜 ...
- resx文件在X64位编译,提示“未能加载文件或程序集”的问题?
原文:resx文件在X64位编译,提示"未能加载文件或程序集"的问题? resx文件在X64位编译,提示"未能加载文件或程序集"的问题? 解答: 错误现象如下 ...
- 改变UIButton 图片和文字的位置
//设置字体和图片之间的间距 _btnLeft.titleEdgeInsets = UIEdgeInsetsMake(0, -_btnLeft.imageView.frame.size.width, ...
- Python开发【第三章】:Python编码转换
一.字符编码与转码 1.bytes和str 之前有学过关于bytes和str之间的转换,详细资料->bytes和str(第四字符串) 2.为什么要进行编码和转码 由于每个国家电脑的字符编码格式不 ...
- Android-Activity使用(1)
一.添加 activity类 Aty1 继承Activity package activitylc.eoe.cn.l002activieylc; import android.app.Activit ...
- ROW_NUMBER
16:23 2015/4/16 删除重复数据,连续被两位同事问到完全相同的重复记录如何删除只保留一条 create table del_samerecords (id )) go insert int ...
- javascript中的真假值、数据类型判断以及+的特殊用法
一.javascript中的假值 jQuery中拥有一组数量奇大的假值,包括 0,NaN(非数),''(空字符串),false,null,undefined 这些值在if判断中全部等于假,但这些值彼此 ...
- 简明python教程 --C++程序员的视角(二):函数及作用域
函数通过def关键字定义.def关键字后跟一个函数的标识符名称,然后跟一对圆括号.圆括号之中可以包括一些变量名,该行以冒号结尾.接下来是一块语句,它们是函数体. 函数的基本概念 1 位置:从左往右进行 ...
- 1029-c语言文法的理解
<程序>→<外部声明>|<程序><外部声明> <外部声明>→<函数定义>|<声明> <函数定义>→< ...