问题 C: Small Multiple
------------本篇为繁花开尽i的注释,那篇博客思路说的太简单
时间限制: 1 Sec 内存限制: 512 MB
提交: 311 解决: 19
[提交] [状态] [讨论版] [命题人:admin]
题目描述
Find the smallest possible sum of the digits in the decimal notation of a positive multiple of K.
Constraints
2≤K≤105
K is an integer.
输入
Input is given from Standard Input in the following format:
K
输出
Print the smallest possible sum of the digits in the decimal notation of a positive multiple of K.
样例输入
6
样例输出
3
提示
12=6×2 yields the smallest sum.
题意:
给出一个数字K,求:K的倍数中,各位数字和最小的数并输出。
思路:
设你要输出的为x,此时这个x对应的k的倍数为y
那么反过来想从1开始一直到当前k对应的x每个数都判断一下,最差是k对应的那个x
这样保证了x的最小
那么看下判断也就是dfs,这是一个一位一位构造y的过程for 0---9
那么y = y*10+ j 这就是构造y的过程,那么%k是为了判断构造出来的y是否为k的倍数
x=x-j则是不断将x分解的过程
如果同时满足x==0&&y==0,即x分解完毕,同时y也是k的倍数说明此时的x满足条件了,
vis数组是因为暴力枚举过程中可能出现循环的情况,那么孜然要排除掉,
又因为x是从1枚举到k对应的x所以第一个满足条件的x即最小的x,也就是答案
2018-8-6,今天 看了数位dp,发现这dfs有点数位dp的意思,看完这个再看数位dp好多了
AC代码:
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define ms(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn = 1e5+5;
int k;
int vis[55][maxn];
int dfs(int x, int y){
if(x < 0) return 0;
if(x == 0 && y == 0)
return 1;
if(vis[x][y]) return 0;
vis[x][y] = 1;
for(int j = 0; j < 10; j++)
if(dfs(x - j, (y * 10 + j) % k))
return 1;
return 0;
}
int main()
{
scanf("%d", &k);
int n = k, s = 0;
while(n){
s += n % 10;
n /= 10;
}
int ans=s;
for(int i=1;i<s; i++) {
if(dfs(i, 0)) {
ans = i;
break;
}
}
printf("%d\n", ans);
return 0;
}
老规矩,别人代码自己敲一遍
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
bool vis[100][100005];
int k;
bool dfs(int x,int y)
{
if(x<0||vis[x][y])return false;
if(!x&&!y)return true;
vis[x][y] = true;
for(int i=0;i<10;i++)
if(dfs(x-i,(y*10+i)%k))
return true;
return false;
}
int main()
{
scanf("%d",&k);
int tk = k;
int sum = 0;
while(tk)
{
sum += tk%10;
tk/=10;
}
int ans = sum;
for(int i=1;i<sum;i++)
{
if(dfs(i,0))
{
ans = i;
break;
}
}
printf("%d\n",ans);
return 0;
}