HDU X mod f(x)(题解注释)
X mod f(x)
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2792 Accepted Submission(s): 1101
Here is a function f(x):
int f ( int x ) {
if ( x == 0 ) return 0;
return f ( x / 10 ) + x % 10;
}
Now, you want to know, in a given interval [A, B] (1 <= A <= B <= 109), how many integer x that mod f(x) equal to 0.
Each test case has two integers A, B.
1 10
11 20
Case 2: 3
/*题意:计算区间内一个数字各位之和能整除该数字的个数
思路:分别计算出[1, b]中符合条件的个数和[1, a-1]中符合条件的个数。
d[l][i][j][k]表示前l位和为i模j的结果为k的数的个数,那么就有方程
d[l+1][i+x][j][(k*10+x)%j] += d[l][i][j][k]
预处理出d[l][i][j][k],然后再逐位统计即可。*/
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std; int bit[];
int dp[][][][];
//d[l][i][j][k]表示前l位和为i模j的结果为k的数的个数
void set()//打表预处理出来你需要的数据
{
int i,j,k,l,x;
for(i = ; i<=; i++)
dp[][][i][] = ;
for(l = ; l<; l++)//枚举的是前l位
for(i = ; i<=l*; i++)//枚举的是当前和,最大和是l*9
for(j = ; j<=; j++)//不可能比81还大,总共才九位数,总和最大就是81,j>81的话得到的就是自己了
for(k = ; k<j; k++)
for(x = ; x<=; x++)//枚举的是当前位上的数
dp[l+][i+x][j][(k*+x)%j] += dp[l][i][j][k];
} //这个(k*10+x)%j是什么意思 //这个状态是前一个状态,位数比等号左边的少一位
//为什么要用k*10+x来模j呐
//因为吧,原来求的是前l位的和,
//现在求得是l+1位的和了,以前的位数
//都向左移动了一位
int solve(int n)
{
if(!n)
return ;
int ans,i,j,k,len;
int sum,tem1,tem2,s,bit[],r;
len = sum = ans = ;
tem1 = tem2 = n;
s = ;
while(tem1)//求每位数之和
{
bit[++len]=tem1%;
tem1/=;
sum+=bit[len];//每位数之和
}
if(n%sum==)//本身要先看是否整除
ans++;
for(i=;i<=len;i++)//前i位
{
sum-=bit[i];//将该位清0
tem2/=;//现在个数是没有个位的
s*=;
tem1=tem2*s;//现在这个数个位上的数是零
for(j=;j<bit[i];j++)//枚举该位的状况(就是遍历这个位上的数)
{
for(k=sum+j;k<=sum+j+*(i-);k++) //该位与更高位的和,而比该位低的和择优9*(i-1)种
{//9*(i-1)因为你枚举每多一位枚举的数字就会多出来9个
if(!k)//和为0的状况不符合
continue;
r=tem1%k;//这里是要保证你枚举到的前i位再加上没枚举到那些位加起来不会超过原来的数
if(r)
r=k-r;//余数大于0,那么k-r得到的数肯定能被k整除
ans+=dp[i-][k-sum-j][k][r];//加上个数
}
tem1+=s/;//标记现在算到哪里,例如1234,一开始t是1230,然后1231,1232,1233,1234,接下来1200,就是1210,1220,1230
}
}
return ans;
} int main()
{
//freopen("in.txt","r",stdin);
int T,l,r,cas = ;
set();//先打表,半打表,将前l位,位数之和是i,并且模上j之后得到k的个数有多少
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&l,&r);
printf("Case %d: %d\n",cas++,solve(r)-solve(l-));
}
return ;
}
自己又写了一遍,虽然都差不多,但是自己写一遍理清了思路
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#define N 10
#define M 82
using namespace std;
int dp[N][M][M][M],g[N];//dp[l][i][j][k]表示前l位的和为i 模上j得数是k的数有多少个
void inti()
{
for(int i=;i<=;i++)
dp[][][i][]=;
//cout<<"ok"<<endl;
for(int l=;l<;l++)//枚举的前l位
for(int i=;i<=l*;i++)//枚举的前l位的和
for(int j=;j<=;j++)//枚举的是你要模的那个数
for(int k=;k<j;k++)//枚举的是模完的结果
for(int x=;x<;x++)//枚举的第l+1位
dp[l+][i+x][j][(k*+x)%j]+=dp[l][i][j][k];
//cout<<"ok"<<endl;
//cout<<"ok"<<endl;
}
int solve(int n)
{
if(!n) return ;
int s,tem1,tem2,sum=,r;
tem1=tem2=n;
s=;
int len=;
while(tem1)
{
g[++len]=tem1%;
tem1/=;
sum+=g[len];
}//分离各位,并且求出来和
int cur=;
if(n%sum==)
cur++;
for(int i=;i<=len;i++)//模拟的是前i位
{
sum-=g[i];//先把这一位清零
tem2/=;
s*=;
tem1=s*tem2;
for(int j=;j<g[i];j++)//枚举的是这个位上的数
{
for(int k=sum+j;k<=sum+j+*(i-);k++)//模拟的是你要模的那个数
{
if(!k) continue;//如果k==0不符合条件
r=tem1%k;
if(r)
r=k-r;
cur+=dp[i-][k-sum-j][k][r];
//cout<<"cur="<<cur<<endl;
//cout<<"dp[i-1][k-sum-j][k][r]="<<dp[i-1][k-sum-j][k][r]<<endl;
}
tem1+=s/;
}
}
return cur;
}
int main()
{
//freopen("in.txt","r",stdin);
//cout<<"ok"<<endl;
inti();
int t,l,r;
scanf("%d",&t);
//cout<<t<<endl;
for(int i=;i<=t;i++)
{
scanf("%d%d",&l,&r);
//cout<<l<<" "<<r<<endl;
printf("Case %d: %d\n",i,solve(r)-solve(l-));
}
return ;
}
HDU X mod f(x)(题解注释)的更多相关文章
- HDU - 4389 X mod f(x)(数位dp)
http://acm.hdu.edu.cn/showproblem.php?pid=4389 题意 为[A,B] 区间内的数能刚好被其位数和整除的数有多少个. 分析 典型的数位dp...比赛时想不出状 ...
- HDU 4389——X mod f(x)(数位DP)
X mod f(x) Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Probl ...
- HDOJ 4389 X mod f(x)
数位DP........ X mod f(x) Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/ ...
- HDU4389:X mod f(x)(数位DP)
Problem Description Here is a function f(x): int f ( int x ) { if ( x == 0 ) return 0; return f ( x ...
- hdu 4389 X mod f(x) 数位DP
思路: 每次枚举数字和也就是取模的f(x),这样方便计算. 其他就是基本的数位Dp了. 代码如下: #include<iostream> #include<stdio.h> # ...
- HDU 4389 X mod f(x)
题意:求[A,B]内有多少个数,满足x % f(x) == 0. 解法:数位DP.转化为ans = solve(b) - solve(a - 1).设dp[i][sum][mod][r]表示长度为i, ...
- HDU 2157 How many ways?? 题解
题目 春天到了, HDU校园里开满了花, 姹紫嫣红, 非常美丽. 葱头是个爱花的人, 看着校花校草竞相开放, 漫步校园, 心情也变得舒畅. 为了多看看这迷人的校园, 葱头决定, 每次上课都走不同的路线 ...
- HDU 2815 Mod Tree 离散对数 扩张Baby Step Giant Step算法
联系:http://acm.hdu.edu.cn/showproblem.php?pid=2815 意甲冠军: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQ ...
- hdu 2815 Mod Tree (exBSGS)
http://acm.hdu.edu.cn/showproblem.php?pid=2815 //解 K^D ≡ N mod P #include<map> #include<cma ...
随机推荐
- Zabbix通过SNMP监控多核CPU使用率时, 计算CPU平均使用率
环境:没有Agent,只能通过SNMP监控时,需要获取多核CPU的平均使用率. ZABBIX的使用SNMP监控CPU使用率时,由于设备都是多核CPU,监控的都是单独某一核心的使用率,但单独某一核使用率 ...
- readfile & file_get_contents异同
记录一下:应用memcache时,准备把整个文件缓存到内存中,遇到了比较奇怪的事情,因为最初使用readfile来读取文件,结果这个函数返回一个字节数,而不是一个字符串,于是文件没办法再输出,最后使用 ...
- 用sqlserver的自定义函数直接获取多级部门全名
好久没写存储过程了,今日正好同事的开发需要,实现显示多级部门的部门全名称. 如 财务部/会计部/会计一部 部门表 人员表 函数 getOrgAllName --OrgID 72 当前的部门ID A ...
- 程序编译没错,运行报错:无法定位程序输入点GT_BufLaserFollowRatio(这是函数)于动态链接库GTS.DLL上
:DLL里面没有导出该函数 :DLL没放进DEBUGS文件夹 (当时的情况是这个)
- 怎样学好哲学(lucas+费马小定理)
怎样学习哲学 时间限制: 1 Sec 内存限制: 128 MB提交: 97 解决: 27[提交][状态][讨论版] 题目描述 OI大师抖儿在夺得银牌之后,顺利保送pku.这一天,抖儿问长者:&qu ...
- 如何修改select标签的默认下拉箭头样式?
对于一般的项目而言,select标签在浏览器中表现出来的默认样式也不算丑,但是一次项目中,项目经理却要求对select标签本身进行样式修改,美化其下拉小箭头的样式.我思考和尝试了许多方法,最终得到一种 ...
- ASP.NET Core 2.0 支付宝当面付之扫码支付
前言 自从微软更换了CEO以后,微软的战略方向有了相当大的变化,不再是那么封闭,开源了许多东西,拥抱开源社区,.NET实现跨平台,收购xamarin并免费提供给开发者等等.我本人是很喜欢.net的,并 ...
- zabbix使用mysql数据库 对表分区
zabbix删除历史数据 mysql 表自动分区.删除 ----2016年终总结 二 zabbix清理历史数据是个比较蛋疼的问题,尤其在监控数据较多时,一方面无法彻底释放历史数据空间,一方面数据库删除 ...
- RN 常见问题
React/RCTBridgeModule.h not found #import <React/RCTBridgeModule.h> 全部替换为 #import "RCTBri ...
- win10 UWP 剪贴板 Clipboard
win10 UWP 剪贴板 Clipboard使用Windows.ApplicationModel.DataTransfer.Clipboard 设置文本 DataPackage dataPackag ...