牛客練習賽75 簡要題解
阿新 • • 發佈:2021-01-09
技術標籤:# 牛客
A-廣義肥波
尤拉降冪。
#include<bits/stdc++.h> #define pb push_back #define fi first #define se second #define sz(x) (int)x.size() #define cl(x) x.clear() #define all(x) x.begin() , x.end() #define rep(i , x , n) for(int i = x ; i <= n ; i ++) #define per(i , n , x) for(int i = n ; i >= x ; i --) #define mem0(x) memset(x , 0 , sizeof(x)) #define mem_1(x) memset(x , -1 , sizeof(x)) #define mem_inf(x) memset(x , 0x3f , sizeof(x)) #define debug(x) cerr << #x << " = " << x << '\n' #define ddebug(x , y) cerr << #x << " = " << x << " " << #y << " = " << y << '\n' #define ios std::ios::sync_with_stdio(false) , cin.tie(0) using namespace std ; typedef long long ll ; typedef long double ld ; typedef pair<int , int> pii ; typedef pair<ll , ll> pll ; typedef double db ; const int mod = 1e9 + 7 ; const int maxn = 2e5 + 10 ; const int inf = 0x3f3f3f3f ; const double eps = 1e-6 ; using namespace std ; struct Easymath { ll qpow(ll a , ll b) //快速冪 { if(b < 0) return 0 ; ll ans = 1 ; a %= mod ; while(b) { if(b & 1) ans = (ans * a) % mod ; b >>= 1 , a = (a * a) % mod ; } return ans % mod ; } ll ksc_log(ll x , ll y , ll mod) //快速乘 { x %= mod , y %= mod ; ll ans = 0; while(y) { if(y & 1) ans = (ans + x) % mod ; y >>= 1 ; x = (x + x) % mod ; } return ans; } ll ksc_O1(ll x , ll y , ll mod) //快速乘 { x %= mod , y %= mod ; ll z = (ld)x * y / mod ; ll ans = x * y - z * mod ; if(ans < 0) ans += mod ; else if(ans >= mod) ans -= mod ; return ans ; } int cnt = 0 ; bool vis[maxn] ; int prime[maxn] ; void get_prime(int up) //素數篩 { memset(vis , 0 , sizeof(vis)) ; vis[1] = 1 ; for(int i = 2 ; i <= up ; i ++) { if(!vis[i]) prime[++ cnt] = i ; for(int j = 1 ; j <= cnt && i * prime[j] <= up ; j ++) { vis[i * prime[j]] = 1 ; if(i % prime[j] == 0) break ; } } } //begin 判定大素數 ll mul(ll a , ll b , ll mod) { ll ret = 0 ; while(b) { if(b & 1) ret = (ret + a) % mod ; a = (a + a) % mod ; b >>= 1 ; } return ret ; } ll pow(ll a , ll b , ll mod) { ll ret = 1 ; while(b) { if(b & 1) ret = mul(ret , a , mod) ; a = mul(a , a , mod) ; b >>= 1 ; } return ret ; } bool check(ll a , ll n) { ll x = n - 1 ; int t = 0 ; while((x & 1) == 0) { x >>= 1 ; t ++ ; } x = pow(a , x , n) ; ll y ; rep(i , 1 , t) { y = mul(x , x , n) ; if(y == 1 && x != 1 && x != n - 1) return 1 ; x = y ; } if(y != 1) return 1 ; return 0 ; } bool Miller_Rabin(ll n) { if(n == 2) return 1 ; if(n == 1 || !(n & 1)) return 0 ; const int arr[12] = {2,3,5,7,11,13,17,19,23,29,31,37} ; rep(i , 0 , 11) { if(arr[i] >= n) break ; if(check(arr[i] , n)) return 0 ; } return 1 ; } //end 判定大素數 ll get_inv(ll x) //逆元 { return qpow(x , mod - 2) % mod ; } ll inv1[maxn] ; //乘法逆元 void init1(int up) { inv1[1] = 1 ; for(int i = 2 ; i <= up ; i ++) inv1[i] = (ll)(mod - mod / i) * inv1[int(mod % (ll)i)] % mod ; } ll fac[maxn] ; ll inv[maxn] ; //階乘逆元 void init(int up) { fac[0] = fac[1] = inv[0] = inv[1] = 1 ; for(int i = 2 ; i <= up ; i ++) { fac[i] = fac[i - 1] * i % mod ; inv[i] = -inv[mod % i] * (mod / i) % mod ; while(inv[i] < 0) inv[i] += mod ; } for(int i = 2 ; i <= up ; i ++) inv[i] = inv[i] * inv[i - 1] % mod ; } ll C(int n , int m) { return fac[n] * inv[m] % mod * inv[n - m] % mod ; } } em ; int main() { ios ; ll a , b , m , n ; cin >> a >> b >> m >> n ; vector<ll> f(n + 1 , 0) ; f[1] = 1 ; f[2] = 1 ; for(int i = 3 ; i <= n ; i ++) f[i] = (a * f[i - 1] % (mod - 1) + b * f[i - 2] % (mod - 1)) % (mod - 1) ; cout << em.qpow(m , f[n]) << '\n' ; return 0 ; }
B-小D和他的魔法石
當時,操作策略是唯一的。
當時,只要使抗力最小的魔法石的魔力最大,然後貪心即可。
#include<bits/stdc++.h> #define pb push_back #define fi first #define se second #define sz(x) (int)x.size() #define cl(x) x.clear() #define all(x) x.begin() , x.end() #define rep(i , x , n) for(int i = x ; i <= n ; i ++) #define per(i , n , x) for(int i = n ; i >= x ; i --) #define mem0(x) memset(x , 0 , sizeof(x)) #define mem_1(x) memset(x , -1 , sizeof(x)) #define mem_inf(x) memset(x , 0x3f , sizeof(x)) #define debug(x) cerr << #x << " = " << x << '\n' #define ddebug(x , y) cerr << #x << " = " << x << " " << #y << " = " << y << '\n' #define ios std::ios::sync_with_stdio(false) , cin.tie(0) using namespace std ; typedef long long ll ; typedef long double ld ; typedef pair<int , int> pii ; typedef pair<ll , ll> pll ; typedef double db ; const int mod = 1e9 + 7 ; const int maxn = 2e5 + 10 ; const int inf = 0x3f3f3f3f ; const double eps = 1e-6 ; using namespace std ; int main() { ios ; ll n , m , k ; cin >> n >> m >> k ; vector<pll> c(n) ; for(int i = 0 ; i < n ; i ++) cin >> c[i].fi ; for(int i = 0 ; i < n ; i ++) cin >> c[i].se ; function<ll()> cal = [&]() { ll res = 0 ; vector<ll> dp(m + 1 , -1e18) ; dp[0] = 0 ; for(int i = 0 ; i < n ; i ++) for(int j = c[i].fi ; j <= m ; j ++) dp[j] = max(dp[j] , dp[j - c[i].fi] + c[i].se) , res = max(res , dp[j]) ; return res ; } ; sort(c.begin() , c.end()) ; ll ans = 0 ; if(n == 2) { if(k % 2 == 1) swap(c[0].se , c[1].se) , ans = cal() , swap(c[0].se , c[1].se) ; else ans = cal() ; } else { ans = max(ans , cal()) ; if(k >= 1) { ll mx = c[0].se ; for(int i = 1 ; i < n ; i ++) mx = max(mx , c[i].se) ; ans = max(ans , m / c[0].fi * mx) ; } } cout << ans << '\n' ; return 0 ; }
C-寶石街
從第個位置開始撿寶石,到第個位置結束撿寶石。那麼的位置的寶石全部取,第個位置的寶石取一部分。雙指標即可。
#include<bits/stdc++.h> using namespace std ; int main() { std::ios::sync_with_stdio(false) ; std::cin.tie(0) ; long long n , t , type ; cin >> n >> t >> type ; vector<long long> a(n) ; if(type == 1) { for(int i = 0 ; i < n ; i ++) cin >> a[i] ; } else { long long p ; cin >> a[0] >> p ; for(int i = 1 ; i < n ; i ++) { long long x = (a[i - 1] ^ (a[i - 1] << 13)) ; long long y = (x ^ (x >> 17)) ; a[i] = (y ^ (y << 5)) % p + 1 ; } } long long ans = 0 ; int j = n - 1 ; long long res = a[n - 1] ; long long sum = 0 ; for(int i = n - 1 ; i >= 0 ; i --) { if(j > i) j -- , assert(res == 0 && sum == 0) , res = a[j] ; while(j - 1 >= 0 && sum + a[j - 1] * (i - (j - 1)) <= t) j -- , res += a[j] , sum += a[j] * (i - j) ; if(j - 1 >= 0) { long long num = (t - sum) / (i - (j - 1)) ; ans = max(ans , res + min(a[j - 1] , num)) ; } ans = max(ans , res) ; res -= a[i] ; sum -= res ; } cout << ans << '\n' ; return 0 ; }
D-減數遊戲
結論是每次取兩個最小的數。但是直接模擬需要高精度。考慮如果不用高精度依然可以表示相對大小。設原序列升序排列後得到。最大的數是,那麼當時,顯然。則每次取序列最靠前的兩個數,合併後塞到隊尾即可。可以取模,也保證了相對大小。
#include<bits/stdc++.h>
using namespace std ;
const int mod = 1e9 + 7 ;
int main()
{
std::ios::sync_with_stdio(false) ;
std::cin.tie(0) ;
int n , k ;
long long mx = 0 ;
cin >> n >> k ;
vector<long long> a(n) ;
for(int i = 0 ; i < n ; i ++) cin >> a[i] , mx = max(mx , a[i]) ;
priority_queue<long long , vector<long long> , greater<long long>> q ;
for(int i = 0 ; i < n ; i ++) q.push(a[i]) ;
while(q.size() > 1)
{
long long a = q.top() ;
q.pop() ;
long long b = q.top() ;
q.pop() ;
q.push(a * b + k) ;
if(a * b + k >= mx) break ;
}
deque<long long> dq ;
while(!q.empty()) dq.push_back(q.top()) , q.pop() ;
while(dq.size() > 1)
{
long long a = dq.front() % mod ;
dq.pop_front() ;
long long b = dq.front() % mod ;
dq.pop_front() ;
dq.push_back((a * b + k) % mod) ;
}
cout << dq.front() % mod << '\n' ;
return 0 ;
}
E-炒雞礦工
表示當前處於第級,花費時間是的最大金礦重量。
轉移方程
具體寫程式碼時不用列舉,正著掃一遍就行了。時間複雜度。
#include<bits/stdc++.h>
using namespace std ;
const int mod = 1e9 + 7 ;
int main()
{
std::ios::sync_with_stdio(false) ;
std::cin.tie(0) ;
long long p , c , n , m , t ;
cin >> p >> c >> n >> m >> t ;
vector<long long> w(n + 1) ;
vector<long long> v(n + 1) ;
vector<long long> s(n + 1) ;
for(int i = 1 ; i <= n ; i ++) cin >> w[i] ;
v[0] = c ;
for(int i = 1 ; i <= n ; i ++) cin >> v[i] , v[i] += v[i - 1] ;
s[0] = p ;
for(int i = 1 ; i <= n ; i ++) cin >> s[i] ;
vector<vector<long long>> dp(n + 1) ;
for(int i = 0 ; i <= n ; i ++) dp[i].resize(t + 1 , -1e18) ;
dp[0][0] = m ;
for(int i = 0 ; i <= n ; i ++)
{
if(i) for(int j = 0 ; j <= t ; j ++) if(dp[i - 1][j] >= w[i]) dp[i][j] = dp[i - 1][j] - w[i] ;
for(int j = s[i] ; j <= t ; j ++) if(dp[i][j - s[i]] >= 0) dp[i][j] = max(dp[i][j] , dp[i][j - s[i]] + v[i]) ;
}
long long ans = 0 ;
for(int i = 0 ; i <= n ; i ++) for(int j = 0 ; j <= t ; j ++) ans = max(ans , dp[i][j]) ;
cout << ans << '\n' ;
return 0 ;
}
F-迷路の小L
首先想到最後一條邊是最長的,然後一通預處理即可。不過細節太多,我就咕咕咕了。