题目
https://projecteuler.net/problem=122
Addition chain
理解
看起来是个描述很简洁的题目
但是 我以为能有什么 局部最优
所以想说 15=3x5,也就是做一次 变3的工作 再一次变5的工作
对于质数 = 1+它的分解
然而错了
想不出什么方法,翻了翻wiki找到了上面的Addition chain
说计算addition chains目前是一个 NP-complete 的问题
好像也并不能dp
于是考虑生成过程,写了一个树上爆搜。
也就是 每个节点的子节点 等于该节点和,该节点以及祖先节点的和
这样就是加法过程,每次新增的数都是最大的。 但是这种情况 其实没有考虑 A-B-C-D-(D+B)-(D+C) , 这样就不是最后一个增加?
这样算法,感觉是有bug的?
虽然这样的代码过了。
不过,我打出了 bfs的 元素个数,看得到仅仅200的数据。191, 已经下标达到了4053954。
然后 我对拍了一下数据,最小的一个不一致是23,需要6步,而我错误的dp是7步
7步: 1+1=2,2+2=4,4+1=5,5+5=10,10+1=11,11+11=22,22+1=23
6步: 1+1=2,2+2=4,4+1=5,5+4=9,9+9=18,18+5=23
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
| #include <bits/stdc++.h> using namespace std;
typedef long long ll; #define t3 1000+10 #define t4 10000+10 #define t5 100000+10 #define t6 1000000+10 #define MOD 1000000007 #define rep(i,a,n) for (ll i=a;i<n;i++) #define per(i,a,n) for (ll i=n-1;i>=a;i--) #define pb push_back const double pi = acos(-1.0);
namespace X{ ll r(){ll r;scanf("%lld",&r);return r;} void add(ll &v0,ll &v1){(v0+=v1%MOD)%=MOD;} ll mpow(ll v,ll mi){ll r = 1;while(mi){if(mi%2)(r*=v)%=MOD;(v*=v)%=MOD;mi>>=1;};return r;} ll mod(ll v){return (v%MOD+MOD)%MOD;} ll gcd(ll a,ll b){return b == 0?a:gcd(b,a%b);} };
ll dp[210]; int p[210];
void wayWrong(){ p[1] = 1; rep(i,2,20){ if(!p[i]){ for(int j = i*i;j<=200;j+=i){ if(!p[j]){ p[j]= i; } } } } rep(i,2,201){ if(!p[i]){ dp[i] = 1+dp[i-1]; }else{ dp[i] = dp[p[i]] + dp[i/p[i]]; } } }
struct Node{ int dep = 0 ; int val = 0; Node * fa = NULL; };
const int N = 10000000;
Node nodes[N+10];
int leftcnt = 200 - 1 ; ll ans[210];
int main(){ int st = 0; int rear = 1; nodes[0].val = 1; while(st < rear){ Node * p = &nodes[st]; while(p != NULL){ int newval = p->val + nodes[st].val; if(newval <= 200){ if(ans[newval] == 0){ printf("%d[dep:%d][bfs idx:%d]\n",newval,nodes[st].dep,rear); ans[newval] = nodes[st].dep + 1; leftcnt--; if(leftcnt == 0){ break; } } nodes[rear].fa = &nodes[st]; nodes[rear].dep = nodes[st].dep+1; nodes[rear].val = newval; rear++; if(rear > N){ printf("leftcnt:%d\n",leftcnt); rep(i,1,201){ if(!ans[i]){ printf("noans:%lld\n",i); } } return 0; } } p=p->fa; } st++; if(leftcnt == 0){ break; } } ll count = 0; rep(i,1,201){ count += ans[i]; } printf("%lld\n",count); return 0; }
|