Codeforces Gym 100531D Digits (暴力、打表)
題目連結
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;
}