Submission #728082

#TimeUsernameProblemLanguageResultExecution timeMemory
728082thomas_liBowling (BOI15_bow)C++17
82 / 100
1078 ms12908 KiB
// yolo #pragma GCC optimize("Ofast,unroll-loops") #pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt") #include <bits/stdc++.h> using namespace std; string rk = "x-"; vector<string> spstr,rgstr; string c1 = "xxx"; vector<string> c2,c3,c4,c5,c6,c7; int n,a[11]; int64_t dp[11][22][22][301]; // first i frames, carry amount from previous i, carry amount from i, score after i // carry is -1 if we don't add string s; void solve(){ memset(dp,0,sizeof dp); cin >> n >> s; s = ' ' + s; for(int i = 1; i <= n; i++) cin >> a[i]; auto can = [&](int i, string& t){ assert(t.size() == 2); for(int j = 0; j < 2; j++){ char c = s[i+j]; if(c == '?') continue; if(c != t[j]) return false; } return true; }; auto can1 = [&](int i, string& t){ assert(t.size() == 3); for(int j = 0; j < 3; j++){ char c = s[i+j]; if(c == '?') continue; if(c != t[j]) return false; } return true; }; dp[0][0][0][0] = 1; auto add = [&](int64_t& x, int64_t y){ x = (x+y); }; // solve normal for(int i = 1; i <= n-1; i++){ // generate good strings bool grk = can(2*i-1,rk); vector<string> gsp,grg; for(auto& t : spstr) if(can(2*i-1,t)) gsp.push_back(t); for(auto& t : rgstr) if(can(2*i-1,t)) grg.push_back(t); swap(gsp,spstr); swap(grg,rgstr); for(int j = -1; j <= 10; j++) for(int k = -1; k <= 20; k++){ // previous previous, previous carries int lo = 0, hi = 270; if(a[i] != -1) lo = hi = a[i]; for(int l = lo; l <= hi; l++){ // cur score // strike // our shot needs to make j zero, k non negative if(grk && (j == -1 || j-10 == 0) && (k == -1 || (k-10 >= 0 && k-10 <= 10))){ // we can gain some more from carries if needed for(int gain = 0; gain <= 20; gain++){ if(l-gain-10 < 0) break; int nk = (k == -1 ? -1 : k-10); add(dp[i][nk+1][gain+1][l],dp[i-1][j+1][k+1][l-gain-10]); } } // spare for(auto& t : spstr){ // previous previous gets subtracted by fs, previous gets subtracted by 10 // both are gone after this frame, so need to become 0 int fs = t[0]-'0',sn = 10; if(j != -1 && j-fs != 0) continue; if(k != -1 && k-sn != 0) continue; for(int gain = 0; gain <= 10; gain++){ if(l-gain-10 < 0) continue; // add to previous slot to satisfy one bonus feature (in theory) add(dp[i][gain+1][0][l],dp[i-1][j+1][k+1][l-gain-10]); } } // regular for(auto& t : rgstr){ // previous previous gets subtracted by fs, previous gets subtracted by sn+fs // both are gone after this frame, so need to become 0 int fs = t[0]-'0',sn = t[1]-'0'; if(j != -1 && j-fs != 0) continue; if(k != -1 && k-fs-sn != 0) continue; if(l-fs-sn < 0) continue; add(dp[i][0][0][l],dp[i-1][j+1][k+1][l-fs-sn]); } /* bool good = 0; for(int z = 0; z <= 20 && !good; z++) for(int w = 0; w <= 20; w++) if(dp[i][z][w][l]){ good = 1; break; } if(good) cout << l << " " << i << "\n"; */ } } swap(gsp,spstr); swap(grg,rgstr); } // solve last // preprocess equalities vector<string> gc2,gc3,gc4,gc5,gc6,gc7; for(auto& t : c2) if(can1(2*n-1,t)) gc2.push_back(t); for(auto& t : c3) if(can1(2*n-1,t)) gc3.push_back(t); for(auto& t : c4) if(can1(2*n-1,t)) gc4.push_back(t); for(auto& t : c5) if(can1(2*n-1,t)) gc5.push_back(t); for(auto& t : c6) if(can1(2*n-1,t)) gc6.push_back(t); for(auto& t : c7) if(can1(2*n-1,t)) gc7.push_back(t); bool gc1 = can1(2*n-1,c1); swap(gc2,c2); swap(gc3,c3); swap(gc4,c4); swap(gc5,c5); swap(gc6,c6); swap(gc7,c7); int64_t ans = 0; for(int j = -1; j <= 10; j++) for(int k = -1; k <= 20; k++){ // previous previous, previous carries int lo = 0, hi = 300; if(a[n] != -1) lo = hi = a[n]; for(int l = lo; l <= hi; l++){ int64_t res = 0; // xxx if(gc1 && (j == -1 || j-10 == 0) && (k == -1 || k-20 == 0) && l-30 >= 0){ add(res,dp[n-1][j+1][k+1][l-30]); } // xxA // condition is same since bonus is only contributed in the first two shots for(auto& t : c2) if((j == -1 || j-10 == 0) && (k == -1 || k-20 == 0)){ int ls = t[2]-'0'; if(l-20-ls < 0) continue; add(res,dp[n-1][j+1][k+1][l-20-ls]); } // xA/ for(auto& t : c3) if(j == -1 || j-10 == 0){ int fs = t[1]-'0',sn = 10-fs; if(k != -1 && k-10-fs != 0) continue; if(l-20 < 0) continue; add(res,dp[n-1][j+1][k+1][l-20]); } // xAB for(auto& t : c4){ int fs = t[1]-'0',sn = t[2]-'0'; if(j != -1 && j-10 != 0) continue; if(k != -1 && k-10-fs != 0) continue; if(l-10-fs-sn < 0) continue; add(res,dp[n-1][j+1][k+1][l-10-fs-sn]); } // A/x for(auto& t : c5) if(k == -1 || k-10 == 0){ int fs = t[0]-'0'; if(j != -1 && j-fs != 0) continue; if(l-20 < 0) continue; add(res,dp[n-1][j+1][k+1][l-20]); } // A/B for(auto& t : c6) if(k == -1 || k-10 == 0){ int fs = t[0]-'0',ls = t[2]-'0'; if(j != -1 && j-fs != 0) continue; if(l-10-ls < 0) continue; add(res,dp[n-1][j+1][k+1][l-10-ls]); } // AB- for(auto& t : c7){ int fs = t[0]-'0',sn = t[1]-'0'; if(j != -1 && j-fs != 0) continue; if(k != -1 && k-fs-sn != 0) continue; if(l-fs-sn < 0) continue; add(res,dp[n-1][j+1][k+1][l-fs-sn]); } ans += res; } } swap(gc2,c2); swap(gc3,c3); swap(gc4,c4); swap(gc5,c5); swap(gc6,c6); swap(gc7,c7); cout << ans << "\n"; } int main(){ cin.tie(0)->sync_with_stdio(0); for(int i = 0; i <= 9; i++){ spstr.push_back(to_string(i) + "/"); c2.push_back("xx"+to_string(i)); c3.push_back("x"+to_string(i)+"/"); for(int j = 0; i+j < 10; j++){ rgstr.push_back(to_string(i)+to_string(j)); c4.push_back("x"+to_string(i)+to_string(j)); c7.push_back(to_string(i)+to_string(j)+"-"); } c5.push_back(to_string(i)+"/x"); for(int j = 0; j <= 9; j++){ c6.push_back(to_string(i)+"/"+to_string(j)); } } int t; cin >> t; while(t--) solve(); } // number of strs for frame: 10 + 1 + 10 // 5726805883325784576

Compilation message (stderr)

bow.cpp: In function 'void solve()':
bow.cpp:131:35: warning: unused variable 'sn' [-Wunused-variable]
  131 |                 int fs = t[1]-'0',sn = 10-fs;
      |                                   ^~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...