2019dx#7
Solved | Pro.ID | Title | Ratio(Accepted / Submitted) |
1001 | A + B = C | 10.48%(301/2872) | |
1002 | Bracket Sequences on Tree | 11.27%(16/142) | |
1003 | Cuber Occurrence | 6.67%(1/15) | |
1004 | Data Structure Problem | 23.08%(3/13) | |
1005 | Equation | 0.00%(0/63) | |
1006 | Final Exam 推公式,田忌赛马 | 5.06%(297/5872) | |
1007 | Getting Your Money Back | 12.42%(20/161) | |
1008 | Halt Hater | 14.77%(61/413) | |
1009 | Intersection of Prisms | 0.00%(0/2) | |
1010 | Just Repeat 博弈,贪心 | 15.04%(128/851) | |
1011 | Kejin Player 期望DP | 21.20%(544/2566) |
1001 A + B = C
题意:
给定a,b,c($a, b, c \le 10 ^{100000}$),求一组x, y, z满足$a \times 10^x + b \times 10^y = c \times 10^z$ 。
思路:
先把每个数末尾的0去掉,然后可以发现满足如下等式之一$$ a + b = c \times 10 ^k $$ $$ a \times 10 ^k + b = c $$ $$ a + b \times 10 ^ k = c$$就行了。
由于是大数,可以利用哈希,计算等式中的k,可以移项,乘逆元,预处理mod意义下指数。
然后我用到双哈希保险
// #pragma GCC optimize(2) // #pragma GCC optimize(3) // #pragma GCC optimize(4) #include <algorithm> #include <iterator> #include <iostream> #include <cstring> #include <cstdlib> #include <iomanip> #include <bitset> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <stack> #include <cmath> #include <queue> #include <list> #include <map> #include <set> #include <cassert> #include <unordered_map> // #include<bits/extc++.h> // using namespace __gnu_pbds; using namespace std; #define pb push_back #define fi first #define se second #define debug(x) cerr<<#x << " := " << x << endl; #define bug cerr<<"-----------------------"<<endl; #define FOR(a, b, c) for(int a = b; a <= c; ++ a) typedef long long ll; typedef unsigned long long ull; typedef long double ld; typedef pair<int, int> pii; typedef pair<ll, ll> pll; const int inf = 0x3f3f3f3f; const ll inff = 0x3f3f3f3f3f3f3f3f; const int mod = 998244353; template<typename T> inline T read(T&x){ x=0;int f=0;char ch=getchar(); while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar(); while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x=f?-x:x; } /**********showtime************/ const int maxn = 1e5+9; const int N = 1e5+9; char a[maxn],b[maxn],c[maxn]; char d[maxn]; int mod1 = 998244353, mod2 = 1e9+7; int ten1[N], ten2[N]; unordered_map<int,int>mp1,mp2; void init(){ ten1[0] = ten2[0] = 1; mp1[1] = mp2[1] = 0; for(int i=1; i<N; i++) { ten1[i] = 1ll*ten1[i-1] * 10 % mod1; ten2[i] = 1ll*ten2[i-1] * 10 % mod2; mp1[ten1[i]] = i; mp2[ten2[i]] = i; } } ll ksm(ll a, ll b, ll mod){ ll res = 1; while(b > 0) { if(b & 1) res = res * a % mod; a = a * a % mod; b = b >> 1; } return res; } int main(){ init(); // debug("ok"); int T; scanf("%d", &T); while(T--) { scanf("%s%s%s", a, b, c); int alen = strlen(a), blen = strlen(b), clen = strlen(c); int cnta = 0, cntb = 0, cntc = 0; while(a[alen-1] == '0') alen--, cnta ++; while(b[blen-1] == '0') blen--, cntb ++; while(c[clen-1] == '0') clen--, cntc ++; int kk = max(cnta, max(cntb, cntc)); a[alen] = '\0'; b[blen] = '\0'; c[clen] = '\0'; ll A1 = 0, B1 = 0, C1 = 0; ll A2 = 0, B2 = 0, C2 = 0; for(int i=0; i<alen; i++){ A1 = (A1 * 10 + (a[i] - '0') ) % mod1; A2 = (A2 * 10 + (a[i] - '0') ) % mod2; } for(int i=0; i<blen; i++){ B1 = (B1 * 10 + (b[i] - '0') ) % mod1; B2 = (B2 * 10 + (b[i] - '0') ) % mod2; } for(int i=0; i<clen; i++){ C1 = (C1 * 10 + (c[i] - '0') ) % mod1; C2 = (C2 * 10 + (c[i] - '0') ) % mod2; } int k1 = (A1 + B1) % mod1 * ksm(C1, mod1-2, mod1) % mod1; if(mp1.count(k1))k1 = mp1[k1]; else k1 = -1; int k2 = (A2 + B2) % mod2 * ksm(C2, mod2-2, mod2) % mod2; if(mp2.count(k2))k2 = mp2[k2]; else k2 = -1; if(k1 == k2 && k1 >= 0) { printf("%d %d %d\n", kk - cnta, kk - cntb, kk + k1 - cntc); continue; } k1 = (C1 - B1) % mod1; if(k1 < 0) k1 += mod1; k1 = k1 * ksm(A1, mod1-2, mod1) % mod1; if(mp1.count(k1))k1 = mp1[k1]; else k1 = -1; k2 = (C2 - B2) % mod2; if(k2 < 0) k2 += mod2; k2 = k2 * ksm(A2, mod2-2, mod2) % mod2; if(mp2.count(k2))k2 = mp2[k2]; else k2 = -1; if(k1 == k2 && k1 >= 0) { printf("%d %d %d\n", kk + k1 - cnta, kk - cntb, kk - cntc); continue; } k1 = (C1 - A1) % mod1; if(k1 < 0) k1 += mod1; k1 = k1 * ksm(B1, mod1-2, mod1) % mod1; if(mp1.count(k1))k1 = mp1[k1]; else k1 = -1; k2 = (C2 - A2) % mod2; if(k2 < 0) k2 += mod2; k2 = k2 * ksm(B2, mod2-2, mod2) % mod2; if(mp2.count(k2))k2 = mp2[k2]; else k2 = -1; if(k1 == k2 && k1 >= 0) { printf("%d %d %d\n", kk - cnta, kk + k1 - cntb, kk - cntc); continue; } puts("-1"); } return 0; }
1006 Final Exam
思路:
假设每个题目所用的时间为$a_1, a_2, ... , a_n(a_i <= a_{i+1})$
按老师的想法,为了不让学生过掉n - k 个题目,肯定是把$a_1, a_2,...a_{n-k}$ 对应题目的分值设为$a_1, a_2,...a_{n-k}$.
然后$$m - a_1 - a_2 - ... - a_{n-k} < a_{n-k+1}$$
我们给左边+1,再移项,变成
$$m + 1 \le + a_1 + a_2 + ... + a_{n-k} + a_{n-k+1}$$
可以发现$a_{n-k+1}$最大会被老师卡成$\left\lceil \frac{m + 1}{n - k + 1} \right\rceil$
之后的$a_{n-k+2},,,a_{n}$可以等于$a_{n-k+1}$就行了。
// #pragma GCC optimize(2) // #pragma GCC optimize(3) // #pragma GCC optimize(4) #include <algorithm> #include <iterator> #include <iostream> #include <cstring> #include <cstdlib> #include <iomanip> #include <bitset> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <stack> #include <cmath> #include <queue> #include <list> #include <map> #include <set> #include <cassert> // #include<bits/extc++.h> // using namespace __gnu_pbds; using namespace std; #define pb push_back #define fi first #define se second #define debug(x) cerr<<#x << " := " << x << endl; #define bug cerr<<"-----------------------"<<endl; #define FOR(a, b, c) for(int a = b; a <= c; ++ a) typedef long long ll; typedef long double ld; typedef pair<int, int> pii; typedef pair<ll, ll> pll; const int inf = 0x3f3f3f3f; const ll inff = 0x3f3f3f3f3f3f3f3f; const int mod = 998244353; template<typename T> inline T read(T&x){ x=0;int f=0;char ch=getchar(); while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar(); while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x=f?-x:x; } /**********showtime************/ int main(){ int T; scanf("%d", &T); while(T--) { ll n, m , k; scanf("%lld%lld%lld", &n, &m, &k); ll tmp = (m + 1) / (n - k + 1); if((m+1) % (n - k + 1)) tmp++; ll ans = (k - 1) * tmp + m+ 1; printf("%lld\n", ans); } return 0; }
1008 Halt Hater
题意:
一开始你在(0, 0)点,面向Y轴正方向。向左走费用为a,向前走费用为b,向右走费用为0。有T($\le 100000$) 组数据,每组给定x,y,a,b,问你到(x,y)的最小费用。
思路:
规律题,首先发现,你到(x-1, y+1)(x, y+1), (x-1, y), (x, y) 其中之一就行了。
然后发现,如果把每个格子看成一个点,那么,相邻格子的费用为a。斜对着的两个格子的费用为min(a, 2 * b)。
一下跨两步的费用为min(2*a, 2*b)。
所以我们首先斜着走,然后两步两步走,然后再走一步。
// #pragma GCC optimize(2) // #pragma GCC optimize(3) // #pragma GCC optimize(4) #include <algorithm> #include <iterator> #include <iostream> #include <cstring> #include <cstdlib> #include <iomanip> #include <bitset> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <stack> #include <cmath> #include <queue> #include <list> #include <map> #include <set> #include <cassert> #include <unordered_map> // #include<bits/extc++.h> // using namespace __gnu_pbds; using namespace std; #define pb push_back #define fi first #define se second #define debug(x) cerr<<#x << " := " << x << endl; #define bug cerr<<"-----------------------"<<endl; #define FOR(a, b, c) for(int a = b; a <= c; ++ a) typedef long long ll; typedef unsigned long long ull; typedef long double ld; typedef pair<int, int> pii; typedef pair<ll, ll> pll; const int inf = 0x3f3f3f3f; const ll inff = 0x3f3f3f3f3f3f3f3f; const int mod = 998244353; template<typename T> inline T read(T&x){ x=0;int f=0;char ch=getchar(); while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar(); while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x=f?-x:x; } /**********showtime************/ ll a, b, x, y; ll check(ll x, ll y) { x = abs(x), y = abs(y); ll ans = 0; ll m = min(x, y); ans += m * min(a, 2ll * b); ll yu = x + y - m - m; ans += (yu / 2) * min(2ll * a , 2ll * b); if(yu % 2 == 1) ans += b; return ans; } int main(){ int T; scanf("%d", &T); while(T--) { scanf("%lld%lld%lld%lld", &a, &b, &x, &y); ll ans = check(x, y); ans = min(ans, check(x-1, y)); ans = min(ans, check(x, y+1)); ans = min(ans, check(x-1, y+1)); printf("%lld\n", ans); } return 0; }