日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

「BJOI2019」奥术神杖(AC自动机+DP)

發(fā)布時(shí)間:2023/12/3 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 「BJOI2019」奥术神杖(AC自动机+DP) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • title
  • solution
  • code

title

solution

Magic=Vi×Vj×Vk...Magic=V_i\times V_j\times V_k...Magic=Vi?×Vj?×Vk?...
這里對(duì)Magicc\sqrt[c]{Magic}cMagic?有一個(gè)很巧妙的轉(zhuǎn)換——取對(duì)數(shù)
Magicc=(Magic)1c=eloge(Magic)1c\sqrt[c]{Magic}=(Magic)^{\frac{1}{c}}=e^{log_e(Magic)^{\frac{1}{c}}}cMagic?=(Magic)c1?=eloge?(Magic)c1?logeMagic1c=1clogeMagic=1cloge(Vi×Vj×Vk...)log_e\ Magic^{\frac{1}{c}}=\frac{1}{c}log_e\ Magic=\frac{1}{c}log_e(V_i\times V_j\times V_k...)loge??Magicc1?=c1?loge??Magic=c1?loge?(Vi?×Vj?×Vk?...)=1c×(logeVi+logeVj+logeVk...)=\frac{1}{c}\times (log_eV_i+log_eV_j+log_eV_k...)=c1?×(loge?Vi?+loge?Vj?+loge?Vk?...)
于是就成功把神力值的相乘開方變?yōu)榱讼嗉?br /> (logeVi+logeVj+logeVk...c)max(\frac{log_eV_i+log_eV_j+log_eV_k...}{c})_{max}(cloge?Vi?+loge?Vj?+loge?Vk?...?)max?👉這個(gè)獅子到這一步就長(zhǎng)得很像0/1分?jǐn)?shù)規(guī)劃問題了
實(shí)際上ta就似

考慮直接二分最后的答案
然后對(duì)咒語建ACACAC自動(dòng)機(jī),在自動(dòng)機(jī)上跑0/10/10/1分?jǐn)?shù)規(guī)劃DPDPDP,判斷答案的大小
failfailfail指針時(shí),順路把從根節(jié)點(diǎn)到nownownow節(jié)點(diǎn)這一條串包含的咒語的信息進(jìn)行類似前綴和的處理

設(shè)dp[i][j]:dp[i][j]:dp[i][j]表示僅考慮前iii個(gè)寶石,現(xiàn)在指向自動(dòng)機(jī)上的jjj節(jié)點(diǎn)時(shí)的最大神力值
iii個(gè)寶石要轉(zhuǎn)移到i+1i+1i+1,就要看iii寶石究竟長(zhǎng)什么模樣
①:殘缺寶石,這個(gè)時(shí)候需要對(duì)始終可能都進(jìn)行轉(zhuǎn)移
②:完整寶石,是什么就轉(zhuǎn)移什么
to:to:to: iii轉(zhuǎn)移i+1i+1i+1jjj指向自動(dòng)機(jī)上的節(jié)點(diǎn)
dp[i+1][to]=max(dp[i][j]+val[to])dp[i+1][to]=max(dp[i][j]+val[to])dp[i+1][to]=max(dp[i][j]+val[to])

code

#include <cmath> #include <queue> #include <cstdio> #include <cstring> using namespace std; #define inf 1e18 #define maxn 1600 #define eps 1e-7 int n, m, tot; queue < int > q; char s[maxn], T[maxn], path[maxn]; int sum[maxn], fail[maxn]; double val[maxn]; int trie[maxn][15]; double dp[maxn][maxn]; int g[maxn][maxn][2];void insert( double v ) {int now = 0, len = strlen( s );for( int i = 0;i < len;i ++ ) {int to = s[i] - '0';if( ! trie[now][to] ) trie[now][to] = ++ tot;now = trie[now][to];}sum[now] ++, val[now] += v; }void Fail() {while( ! q.empty() ) q.pop();fail[0] = 0;for( int i = 0;i < 10;i ++ )if( trie[0][i] ) {fail[trie[0][i]] = 0;q.push( trie[0][i] );}while( ! q.empty() ) {int now = q.front(); q.pop();sum[now] += sum[fail[now]];val[now] += val[fail[now]];for( int i = 0;i < 10;i ++ ) {if( trie[now][i] ) {fail[trie[now][i]] = trie[fail[now]][i];q.push( trie[now][i] );}elsetrie[now][i] = trie[fail[now]][i];}} }double DP( double x ) {for( int i = 0;i <= n;i ++ )for( int j = 0;j <= tot;j ++ )dp[i][j] = -inf;for( int i = 0;i <= tot;i ++ ) val[i] -= sum[i] * x;dp[0][0] = 0;for( int i = 0;i < n;i ++ ) { //前i個(gè)字符for( int j = 0;j <= tot;j ++ ) { //現(xiàn)在在AC自動(dòng)機(jī)上的j節(jié)點(diǎn)if( dp[i][j] <= -inf ) continue; //dp[i][j]:最大魔術(shù)值for( int k = 0;k < 10;k ++ ) if( T[i] == '.' || T[i] == k + '0' ) {int to = trie[j][k];if( dp[i + 1][to] < dp[i][j] + val[to] ) {dp[i + 1][to] = dp[i][j] + val[to];g[i + 1][to][0] = j, g[i + 1][to][1] = k;//0:記錄點(diǎn) 1:記錄邊的字符 后面還原路徑用}}}}for( int i = 0;i <= tot;i ++ ) val[i] += sum[i] * x;int ans = 0;for( int i = 0;i <= tot;i ++ )if( dp[n][i] > dp[n][ans] ) ans = i;int pos = ans;for( int i = n;i;i -- )path[i] = g[i][pos][1] + '0', pos = g[i][pos][0];return dp[n][ans]; }int main() {scanf( "%d %d %s", &n, &m, T );for( int i = 1, v;i <= m;i ++ ) {scanf( "%s %d", s, &v );insert( log( v ) );}Fail();double l = 0, r = 1e9, ans;while( r - l > eps ) {double mid = ( l + r ) / 2;if( DP( mid ) > 0 ) ans = mid, l = mid;else r = mid;}DP( ans );printf( "%s", path + 1 );return 0; }

總結(jié)

以上是生活随笔為你收集整理的「BJOI2019」奥术神杖(AC自动机+DP)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。