Submission #728093

#TimeUsernameProblemLanguageResultExecution timeMemory
728093thomas_liBowling (BOI15_bow)C++17
100 / 100
92 ms6612 KiB
#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][12][22][301],tmp[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; bool canrg[10][10]; void solve(){ cin >> n >> s; s = ' ' + s; for(int i = 1; i <= n; i++){ cin >> a[i]; for(int j = 0; j < 12; j++) for(int k = 0; k < 22; k++){ memset(dp[i][j][k],0,8*(30*i+1)); } } 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); int lo = 0, hi = 30*i; if(a[i] != -1) lo = hi = a[i]; for(int j = -1; j <= 10; j++) for(int k = -1; k <= 20; k++){ // previous previous, previous carries memcpy(tmp,dp[i-1][j+1][k+1],301*8); // 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))){ int nk = (k == -1 ? -1 : k-10); // we can gain some more from carries if needed for(int gain = 0; gain <= 20; gain++){ // l >= gain+10 //if(l-gain-10 < 0) break; for(int l = max(lo,gain+10); l <= hi; l++) add(dp[i][nk+1][gain+1][l],tmp[l-gain-10]); } } // spare if(k == -1 || k-10 == 0){ // TODO: opt break 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'; if(j != -1 && j-fs != 0) continue; for(int gain = 0; gain <= 10; gain++){ //if(l-gain-10 < 0) break; // add to previous slot to satisfy one bonus feature for(int l = max(lo,gain+10); l <= hi; l++) add(dp[i][gain+1][0][l],tmp[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; for(int l = max(lo,fs+sn); l <= hi; l++) add(dp[i][0][0][l],tmp[l-fs-sn]); } } 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 res = 0; int lo = 0, hi = 300; if(a[n] != -1) lo = hi = a[n]; for(int j = -1; j <= 10; j++) for(int k = -1; k <= 20; k++){ // previous previous, previous carries memcpy(tmp,dp[n-1][j+1][k+1],301*8); if((j == -1 || j-10 == 0) && (k == -1 || k-20 == 0)){ // xxx if(gc1) for(int l = max(lo,30); l <= hi; l++) add(res,tmp[l-30]); // xxA // condition is same since bonus is only contributed in the first two shots for(auto& t : c2) { int ls = t[2]-'0'; for(int l = max(lo,20+ls); l <= hi; l++) add(res,tmp[l-20-ls]); } } if((j == -1 || j-10 == 0)){ // xA/ for(auto& t : c3) { int fs = t[1]-'0'; if(k != -1 && k-10-fs != 0) continue; for(int l = max(lo,20); l <= hi; l++) add(res,tmp[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; for(int l = max(lo,10+fs+sn); l <= hi; l++) add(res,tmp[l-10-fs-sn]); } if(k == -1 || k-10 == 0){ // A/x for(auto& t : c5) { int fs = t[0]-'0'; if(j != -1 && j-fs != 0) continue; for(int l = max(lo,20); l <= hi; l++) add(res,tmp[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; for(int l = max(lo,10+ls); l <= hi; l++) add(res,tmp[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; for(int l = max(lo,fs+sn); l <= hi; l++) add(res,tmp[l-fs-sn]); } } swap(gc2,c2); swap(gc3,c3); swap(gc4,c4); swap(gc5,c5); swap(gc6,c6); swap(gc7,c7); cout << res << "\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
#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...