標籤:blog http os 2014 io for
題目連結:點擊開啟連結
題意:
一個遊戲由3個人輪流玩
每局遊戲由其中一名玩家選擇一個數字作為開始
目的:獲得最小的得分
對於當前玩家 O ,面對 u 這個數字
則他的操作有:
1、 計分 u +1 ,然後 u++;
2、計分 u / x, 然後 u /= x; 其中x為u的因子且x為素數
然後下一個玩家繼續上述操作
3個人各操作一次 為1輪
當一輪結束後,若u==1 則遊戲結束
每個人的得分為 他所有計分記錄裡最小的數字
若在一輪結束前 u就==1, 那麼玩家的得分為本局遊戲的初始數
求:
每個人在採取最優操作下玩n局遊戲的總得分(不同局得分相加)
輸入n表示n局遊戲
下面n行給定 人名縮寫+u
表示哪個玩家開始,他選擇了哪個數字
思路:
1、n局遊戲之間各不影響,所以分開考慮每局遊戲
2、對於一局遊戲,則我們可以記憶化搜尋出每個數字u對應的狀態
顯然我們可以得到若u為素數時 答案就是 { 1, u, u}
若u不為素數,則u可以轉移到狀態v
在保證第一個數字最小的情況下,從越小的狀態轉移過來則結果越小
注意素數初始化時我們認為是{prime, inf, inf} 這樣會得到一些不存在狀態,而不存在的狀態意義是本局遊戲的初值
#include <stdio.h>#include <algorithm>#include<iostream>#include<string.h>#include <math.h>#include<queue>#include<map>#include<vector>#include<set>using namespace std;#define N 100008#define inf 100000000#define ll intll prime[9599], primenum;set<int>s;void PRIME(ll Max_Prime){primenum = 0;prime[primenum++] = 2;for(ll i = 3; i <= Max_Prime; i+= 2)for(ll j = 0; j < primenum; j++)if(i%prime[j]==0)break;else if(prime[j] > sqrt((double)i) || j==primenum-1){prime[primenum++] = i;break;}}struct node{int a,b,c,ok;node(int x=0,int y=0,int z=0,int yes=0):a(x),b(y),c(z),ok(yes){}}dp[N];void dfs(int u){if(dp[u].ok)return;int t, fir = inf, id = inf;for(int i = 0; prime[i] <= u; i++)if(u % prime[i]==0) {dfs(u/prime[i]);t = min(u/prime[i], dp[u/prime[i]].c);if(t < fir || (t == fir && u/prime[i] < id))fir = t, id = u/prime[i];}dfs(u+1);t = min(u+1, dp[u+1].c);if(t < fir || (t == fir && u+1 < id))fir = t, id = u+1;dp[u] = node( fir, dp[id].a, dp[id].b, true);}int main(){int i, n;PRIME(100007);s.clear();for(i = 0; i < N; i++) dp[i].ok = false;for(i = 0; i < primenum; i++) {dp[prime[i]] = node(1, inf, inf, true);s.insert(prime[i]);}dp[1] = node(1, 1, 1, true);while(~scanf("%d",&n)){node ans = node(0, 0, 0, true);while(n--){char ch[2]; int u;scanf("%s %d", ch, &u);dfs(u);node tmp = dp[u];if(tmp.a == inf) tmp.a = u;if(tmp.b == inf) tmp.b = u;if(tmp.c == inf) tmp.c = u;if(ch[0] == 'O')ans.a += tmp.a, ans.b += tmp.b, ans.c += tmp.c;else if(ch[0] == 'E')ans.b += tmp.a, ans.c += tmp.b, ans.a += tmp.c;elseans.c += tmp.a, ans.a += tmp.b, ans.b += tmp.c;}printf("%d %d %d\n", ans.a,ans.b, ans.c);}return 0;}