codeforces E. Generate a String

題目轉送門:http://codeforces.com/problemset/problem/710/E
思路:這是yveh神犇扔給我的,他都懶得做這樣簡單的題QAQ
不過這確實是CF有史以來最傻逼的一道題?
我的傻逼做法:
考慮直接dp,設f[i] 爲數i 時的答案
考慮暴力轉移有兩種,f[i]=min(f[i1]+x,f[j]+y+(2ji)x(j>=(i+1)/2))
考慮優化轉移二,相當於取min(f[j]+2jx)
一個性質是abs(f[i]f[i1])<=x (根據轉移一得到)
所以 min(f[j]+2jx) 這玩意每次增量爲2x 肯定單調遞增
所以直接轉移就好了,代碼奇短。
由ISA神犇提供更強做法:
考慮這個操作序列其實是2+1 /1 ,考慮它的性質,一定滿足兩個相鄰的2 之間的1 的個數至多一個,因爲多餘的可以提出到前面去,根據這個性質dfs即可。
複雜度在O(logn) 左右

dp:
代碼:

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#define N 10000000
using namespace std;
typedef long long LL;
LL f[N + 5],n,x,y;
int main(){
    cin>>n>>x>>y;
    f[1] = x;
    for (int i = 2;i <= n; ++i){
      f[i] = f[i - 1] + x;
      if (i & 1)
      f[i] = min(f[i],f[(i + 1)>>1] + y + x);
      else f[i] = min(f[i],f[i >> 1] + y); }
    cout<<f[n];
    return 0; 
} 

總結:1.優化轉移的時候考慮某些式子的單調性
2.考慮將操作視爲操作序列,尋找最優操作序列的性質
3.一道題的做法不止一種,也不要滿足於給定的科學的複雜度,要從不同角度理解問題,追求不同的更優的複雜度,努力找出多種做法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章