【CodeForces - 1066A~E】水题,模拟(有技巧),思维,题意难懂的模拟,二进制问题(有技巧)
A.
題目大意:
? ?x坐標(biāo)上1~L有L個(gè)點(diǎn)都是整數(shù),每v個(gè)長(zhǎng)度就有一個(gè)燈亮著,但是有 [ l , r ] 這段區(qū)間上有列火車擋住了,問(wèn)你能看到多少亮燈。
解題報(bào)告:
? ?大水題啊,找?guī)讉€(gè)樣例就會(huì)發(fā)現(xiàn)需要特殊處理一下左邊界恰好有燈的情況。
AC代碼:
#include<bits/stdc++.h>using namespace std; int L,v,l,r,ans; int main() {int t;cin>>t;while(t--) {scanf("%d%d%d%d",&L,&v,&l,&r);ans = (L/v) - (r/v - l/v);if(l%v==0) ans--;printf("%d\n",ans);}return 0 ; }?
B.
題目大意:
? ? 一個(gè)大小為n的數(shù)組代表n個(gè)房間,數(shù)組第i個(gè)元素為1代表在第i個(gè)房間有一個(gè)熱水器,可以熱給范圍為[i-r+1,i+r-1]范圍的房間熱水,問(wèn)最少需要多少熱水器,可以供給所有房間。
解題報(bào)告:
? ?模擬一下過(guò)程就好了,記得終點(diǎn)不是在n,而是要加一個(gè)常數(shù)。因?yàn)橛心且徊絠=cur,所以時(shí)間不是線性的,而是近似o(n^2)了。
AC代碼:
#include<bits/stdc++.h>using namespace std; int a[100005]; int main() {int n,r,flag=1;cin>>n>>r;r--;for(int i = 1; i<=n; i++) scanf("%d",a+i);int cur = 0,now = 0,cnt = 0;int pos = 1;for(int i = 1; i<=n+2000; i++) {if(pos > n) break;if(a[i] == 1) {if(i-pos <= r) {now = i;}}if(i-pos > r) {if(now == cur) {flag=0;break;}cnt++;cur=now;pos = cur + r + 1;i=cur;}}if(flag == 0) puts("-1");else printf("%d\n",cnt);return 0 ; }另附一種模擬思路:(就是徹徹底底的o(n^2)了,每次都從末尾開(kāi)始找,找到的第一個(gè)滿足條件的一定是我們喜歡的,不過(guò)反正n很小,n^2也不慫,主要是這種思路不容易寫(xiě)萎了啊)
#include<bits/stdc++.h> #define ll long long using namespace std; const int MAX = 1e3+5; int n,r; int a[MAX]; int main() {scanf("%d%d",&n,&r);for(int i=1; i<=n; i++)scanf("%d",&a[i]);int last = 0,num = 0;bool flag;int pos;while(1) {if(last>=n) break; flag = false;int pp = max(last-r+1,0);for(int i=n; i>pp; i--) {if(a[i]) {if(i-r<=last) {pos = i;flag = true;break;}}}if(!flag) {printf("-1\n");return 0;}last = pos+r-1;num++;}printf("%d\n",num);return 0; }wjh的代碼:
#include<bits/stdc++.h> #include<queue> using namespace std; int a[2000]; int main() {int n,r;scanf("%d%d",&n,&r);for(int i=1; i<=n; i++) {scanf("%d",&a[i]);}int d=r;int flag=0;for(int i=r; i>=1; i--) {if(a[i]==1) {flag=i;break;}}int ans=1;if(flag==0) {printf("-1\n");} else {int wi=flag;int ff=0;while(wi+r-1<n) {d=wi+r+r-1;ff=0;for(int i=d; i>wi; i--) {if(a[i]==1) {ff=1;wi=i;ans++;break;}}if(ff==0)break;}if(wi+r-1>=n)printf("%d\n",ans);else {printf("-1\n");}}return 0; }?剛開(kāi)始? ?在最后判斷的時(shí)候?qū)懗闪薸f(ff=0),就錯(cuò)了,因?yàn)闈M足不了第一次就完成的 ?就進(jìn)不去while了?
C.
題目大意:
開(kāi)始空隊(duì)列,三種操作,可以進(jìn)行前插和后插,查詢使某個(gè)數(shù)的為最左或最右需要去掉的最少數(shù)字(其實(shí)也就是距離隊(duì)列最左端或者最右端哪個(gè)更近)。
解題報(bào)告:
? ?這題如果想著,每次加入一個(gè)答案都去維護(hù)之前的所有的值,那就走遠(yuǎn)了。這題完全可以記錄一下位置然后中間完全不用維護(hù),最后直接輸出結(jié)果就可以了。
#include<bits/stdc++.h>using namespace std; int q,l,r,tmp; char op[5]; int a[500005]; int main() {cin>>q;l = 0,r = 0;for(int i = 1; i<=q; i++) {scanf("%s",op);if(op[0] == 'L') {scanf("%d",&tmp);a[tmp] = --l;if(i == 1) r--;}else if(op[0] == 'R') {scanf("%d",&tmp);a[tmp] = ++r;if(i == 1) l++;}else {scanf("%d",&tmp);printf("%d\n",min(r-a[tmp],a[tmp]-l));}}return 0 ; }?
D.
題目大意:
有n個(gè)物品,、第一給物品開(kāi)始往右邊挑選,對(duì)于每一個(gè)物品,如果可以放得下的就直接放進(jìn)盒子,若目前的盒子放不下,那就要另外開(kāi)一個(gè)盒子來(lái)放物品了,若目前還有可用的盒子,那就繼續(xù)選取下去,若目前已經(jīng)沒(méi)有可用的盒子了,說(shuō)明這次選取是不對(duì)的,那么選取的第一個(gè)物品退回去,看是否有剩余的空間放下該物品,如果還是放不下的話,繼續(xù)把第二個(gè)拿的物品退回去,直至可以放下該物品為止,然后繼續(xù)選取下去。
解題報(bào)告:
? 讀懂題了就很簡(jiǎn)單,就是往盒子里按照給定的順序放東西,如果放滿了就新開(kāi)一個(gè)盒子放東西,如果都滿了,那就把最早放入的物品拿出來(lái),然后繼續(xù)放后面的物品,直到放到最后一個(gè)物品。問(wèn)你盒子中最多有多少物品?。。。就是這一句話,好有迷惑性,一般都會(huì)感覺(jué)是中間過(guò)程也會(huì)算上,而且不能打亂順序放,所以不能排序,就是必須按照他的algorithm放東西,所以就不好模擬了啊!但是其實(shí)題意是就問(wèn)你最后盒子中物品的數(shù)量,而不是中間某個(gè)過(guò)程就算物品很多,也被拿出來(lái)了,那也 白搭,所以只和最終狀態(tài)有關(guān),,這樣正著還是不好模擬,所以采用時(shí)光倒流法,,,倒著模擬,就簡(jiǎn)單多了,或者先二分從第幾個(gè)盒子開(kāi)始裝,然后再驗(yàn)證是否可行即可(也可以二分最終裝了多少個(gè)物品,不過(guò)其實(shí)一樣的因?yàn)榉凑际堑怪b)。不過(guò)這個(gè)題的二分沒(méi)啥亂用,,因?yàn)橹苯幽M就出結(jié)果了。
#include <bits/stdc++.h> #define ll long longusing namespace std; int n,box,siz; int a[200005];bool ok(int mid){int k=1,rem=siz;for(int i = mid; i<=n; i++){if(rem<a[i]){rem=siz;k++;}if(k>box) return 0;rem-=a[i];}return 1; } int main() {cin>>n>>box>>siz;for(int i = 1; i<=n; i++) cin>>a[i];int mid,l=1,r=n,ans;while(l<=r){mid=(l+r)/2;if(ok(mid))ans=mid,r=mid-1;else l=mid+1;}cout << n + 1 -ans << endl;return 0; }?
E.
題目大意:
? ?給你長(zhǎng)度分別為n,m的二進(jìn)制串,當(dāng)b>0時(shí),對(duì)a,b,&運(yùn)算結(jié)果為tmp,然后b右移一位,把每次a&b的10進(jìn)制結(jié)果(tmp)累加得到sum,結(jié)果輸出sum對(duì)998244353取余的值。
解題報(bào)告:
? 模擬過(guò)程不難發(fā)現(xiàn),a的每一個(gè)位置做出的貢獻(xiàn)次數(shù),就是b對(duì)應(yīng)位置前綴1的個(gè)數(shù),于是維護(hù)一下就好了。(因?yàn)閎字符串一直在變,但是a是固定不變的啊!所以我們預(yù)處理一下a字符串)
#include<bits/stdc++.h> #define ll long long using namespace std; int n,m; const ll mod = 998244353; char op[5]; char a[500005],b[500005]; ll ans[500005]; ll qpow(ll a,ll k) {ll res = 1;while(k) {if(k&1) {res *= a;res %= mod;}k>>=1;a=(a*a)%mod;}return res; } int main() {ll cha = 0;cin>>n>>m;cin>>(a+1);cin>>(b+1);ll lena = strlen(a+1);ll lenb = strlen(b+1);ll cur = 0;if(strlen(a+1) < strlen(b+1)) {cha = strlen(b+1) - strlen(a+1);for(ll i = 1; i<=cha; i++) {if(b[i] == '1') cur++;}for(ll i = 1; i<=strlen(a+1); i++) {if(b[i+cha]=='1') ans[i] = ++cur;else ans[i]=cur;}}else {cha = strlen(a+1) - strlen(b+1);for(ll i = 1; i<=strlen(b+1); i++) {if(b[i] == '1') ans[i+cha] = ++cur;else ans[i+cha] = cur;}}ll out = 0;for(ll i = 1; i<=strlen(a+1); i++) {if(a[i] == '1') {out += (ll)ans[i] * qpow(2,lena-i);out %= mod;}}printf("%lld\n",out%mod);return 0 ; }比賽的時(shí)候忘記考慮a比b長(zhǎng)的情況了、、不然這場(chǎng)比賽完美了啊。?最后壓哨失敗很難受。。
這道題還有更精彩更簡(jiǎn)潔的解法,把兩個(gè)字符串處理成相同長(zhǎng)度的,再去維護(hù),豈不是美滋滋?正好用到了string類,重載 ' + ' 焦作人啊!另外,這個(gè)代碼中預(yù)處理了2^n,做到了o(1)出結(jié)果,比快速冪的log要好一些。
AC代碼2:
#include<bits/stdc++.h> using namespace std; #define ll long long const ll mod=998244353; const ll N=2e5+10; ll one[N],pw[N]; int main() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); ll i,j,k,n,m;string a,b;cin>>n>>m;cin>>a>>b;//使位數(shù)一致在位數(shù)少的前面加0 if(n<m){a=string(m-n,'0')+a;}else if(m<n){b=string(n-m,'0')+b;}n=max(n,m);one[0]=(b[0]=='1');for(i=1;i<n;i++) one[i]=one[i-1]+(b[i]=='1');//b高位開(kāi)始的前綴和 pw[0]=1;for(i=1;i<N;i++) pw[i]=pw[i-1]*2ll%mod;//計(jì)算2的冪次預(yù)處理 ll ans=0;for(i=0;i<n;i++){ll res=(a[i]=='1');res=res*pw[n-i-1]%mod;//計(jì)算a這個(gè)位置的10進(jìn)制值 ans=(ans+res*one[i]%mod)%mod;//之所以*one[i],是因?yàn)閎右移的過(guò)程,a[i]對(duì)應(yīng)的次數(shù)就是b高位開(kāi)始的前綴和,注意取余mod }cout<<ans<<endl;return 0; }?
總結(jié)
以上是生活随笔為你收集整理的【CodeForces - 1066A~E】水题,模拟(有技巧),思维,题意难懂的模拟,二进制问题(有技巧)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 宣称可抗幽门螺旋杆菌 薇娅丈夫公司违反广
- 下一篇: 不怕删错了!微信iOS版8.0.24更新