题目链接
1.暴力打表。。。
上来队友开始推规律
n
1 1= 1
2 11= 1 + 10
3 33= 2 + 11 + 20
4 66= 3 + 12 + 21 + 30
5 110= 4 + 13 + 22 + 31 + 40
6 165= 5 + 14 + 23 + 32 + 41 + 50
7 231= 6 + 15 + 24 + 33 + 42 + 51 + 60
8 308= 7 + 16 + 25 + 34 + 43 + 52 + 61 + 70
9 396= 8 + 17 + 26 + 35 + 44 + 53 + 62 + 71 + 80
10 495= 9 + 18 + 27 + 36 + 45 + 54 + 63 + 72 + 81 + 90
11 603= 9 + 18 + 27 + 36 + 45 + 54 + 63 + 72 + 81 + 90 + 108
12 720= 9 + 18 + 27 + 36 + 45 + 54 + 63 + 72 + 81 + 90 + 108 + 117
推到这里,队友说之后的只能是各位数字之和为9的数加起来和最小
于是我简单的打了个表
int cnt=0;
ll sum=0;
for(int i=1; i<=10000000; i++)
{
if(getsum(i) == 9) //getsum()是求各位数字之和
{
sum+=i;
cnt++;
book[cnt] = sum;
}
if(cnt == 5000) break;
}
如此暴力的把n=10以后的答案都算出来了。。
结果WA在了第八组上
我开始debug。。。一直觉得题面给的除以9是个暗示。。。
所以改了挺长时间也没出,直到我觉得需要试一下各位数之和等于别的情况修改getsum(i) == 15 book[5000]小了很多
当getsum(i)==10 book[39] 就比 个位数字之和等于9的book[39]小
所以我有了个大胆的想法= = 我试了一些数 发现当getsum(i)==20 时
或者再往后 它的book[5000]开始不再变小,开始稳定不变。
代码就出来了
。。。略微暴力
最坏的求各位数字之和是分解十次 所以最坏的时间复杂度是10^8次幂吧
但是由于有剪枝和大多数数字到不了十位,所以还是会好很多。
#include <iostream>
#include <cstring>
#include <cstdio>
#define ll long long
using namespace std;
ll book[5005];
ll getsum(int x)
{
int sum=0;
while(x)
{
sum+=x%10;
x = x/10;
}
return sum;
}
int main()
{
int n;
for(int k=9; k<=20; k++)
{
int cnt=0;
ll sum=0;
for(int i=1; i<=10000000; i++)
{
if(getsum(i) == k)
{
sum+=i;
cnt++;
if(k==9)
book[cnt] = sum;
else book[cnt] = min(book[cnt],sum);
}
if(cnt == 5000) break;
}
}
book[1] = 1;
book[2] = 11;
book[3] = 33;
book[4] = 66;
book[5] = 110;
book[6] = 165;
book[7] = 231;
book[8] = 308;
book[9] = 396;
book[10] = 495;
//freopen("digits.in", "r", stdin);
//freopen("digits.out", "w", stdout);
while(cin>>n)
{
printf("%lld\n",book[n]);
}
return 0;
}
2.来自大牛们的科学暴力法:
来源博客
这个的思路就是存下 在1到100000中 每种各位数字之和的出现次数,并在结构体中存下这个各位数字之和的最小和 。
然后输入n 匹配次数。 他在测试中得到正确答案也一定是测试了很多范围最终确定100000
/********************************************************
题意:给你一个n表示需要你找n个数字,每个数字的各个位数之
和必须相等,求最小的n个数字之和
类型:暴力
分析:因为n个数字都必须是正整数,由n<=5000, 暴力测试发现
1~100000以内可以得到5000个正解,由1~100000每个数字最大分
解次数<=10,暴力解决这道题的复杂度<10^6
*********************************************************/
#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
struct node{
long long sum;
int cishu;
}a[100];
int main(){
//freopen("digits.in","r",stdin);
//freopen("digits.out","w",stdout);
int n;
scanf("%d",&n);
long long b=0xfffffff;
for(int i=1;i<=100000;i++){
int tmp=i;
int summ=0;
while(tmp){
summ+=tmp%10;
tmp/=10;
}
a[summ].cishu++;
a[summ].sum+=i;
if(a[summ].cishu==n){
if(a[summ].sum<b)b=a[summ].sum;
}
}
cout<<b<<endl;
}