【Codeforces 1461E】Water Level
阿新 • • 發佈:2020-12-20
題目連結
翻譯
讓你維持水位始終在 [l,r] 這個範圍
且,你每天開始的時候可以加(所以也可以不加) \(y\) 升水,然後結束的時候會少掉 \(x\) 升水(固定)。
一開始水位是 \(k\),問你這樣(水位始終在 [l,r] 這個區間) 能否持續 \(t\) 天。
題解
如果 \(y<x\),那麼顯然水位只會一直下降。則一開始如果水位大於 \(r-y\) 那麼就每次只減少 \(x\)。到了 \(r-y\) 以後,每次能增加 \(y\) 了。
則每次減少 \(x-y\)。模擬一下就好,注意如果一直減 \(x\)
嗯。。現在跟你說這些你又怎麼會懂呢,自己寫程式碼試試(WA一下)就知道了hhh
如果 \(y>=x\), 那麼一個比較機智的方法就是,一直減 \(x\) 減到 \(k-x*((k-l)/x)\) 即左邊界的邊緣。然後再加一次 \(y\),然後再減 \(x\) 減到
邊緣。這樣是不是沒有止境了呢? 不是的,因為你每次減到邊緣之後,水位其實就是 \(l+(k-l+times*y)\%x\), 這裡的 \(times\) 就是你每次加一次 \(y\) 總共加的
次數。這顯然是有迴圈節的,而 \(x\)
出現了迴圈節就直接輸出 \(Yes\) 就好。
程式碼
#include <bits/stdc++.h> #define LL long long using namespace std; const int X = 1e6; vector<int> ans; LL k,l,r,t,x,y; bool bo[X+10]; void _judge(LL days){ if (days >= t){ cout << "Yes" << endl; }else{ cout << "No" << endl; } } int main(){ // freopen("C://1.cppSourceProgram//rush.txt","r",stdin); ios::sync_with_stdio(0),cin.tie(0); //1 input data cin >> k >> l >> r >> t >> x >> y; //2 y < x continue subtraction if (y < x){ LL t0 = 0; //3 sub x first until that k+y <= r ie. k<=r-y // if (k>r-y){ //4 r-y < l no add just go die if (r - y < l){ t0 = (k-l)/x; _judge(t0); return 0; }else{ //5 r - y >= l, cal first t0 days to let k <=r-y t0 = (k-(r-y)-1)/x+1; k -= t0*x; } } //k <= r-y //6 k < l ->output t0 if (k < l){ //最後一天不能加上 t0--; _judge(t0); return 0; } //7 l <= k <= r-y //add y sub x and x > y LL t1 = (k-l)/(x-y); _judge(t0+t1); }else{ // y >= x //8 增加的比減少的多 //減到不能減為止,然後開始加。再減到不能減為止,再加一次。直到出現迴圈,或者超出界限。 // 9 先減到不能減為止 LL t0 = 0; t0 += (k-l)/x; k -= t0*x; // 10 令 delta = k-l LL delta = k - l; // 開始讓這個數加 y 然後對 x 取模(對應再減到不能減)。直到出現重複為止。 bo[delta] = true; delta = delta+y; while (delta <= r-l){ t0 += delta/x; if (t0>=t){ break; } delta = delta%x; if (bo[delta]){ t0 = t; break; } bo[delta] = true; delta = delta + y; } _judge(t0); } return 0; }