Neko's loop
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 795 Accepted Submission(s): 144
c++
Problem Descriptionapp
Neko has a loop of size n.
The loop has a happy value ai on the i−th(0≤i≤n−1) grid.
Neko likes to jump on the loop.She can start at anywhere. If she stands at i−th grid, she will get ai happy value, and she can spend one unit energy to go to ((i+k)modn)−th grid. If she has already visited this grid, she can get happy value again. Neko can choose jump to next grid if she has energy or end at anywhere.
Neko has m unit energies and she wants to achieve at least s happy value.
How much happy value does she need at least before she jumps so that she can get at least s happy value? Please note that the happy value which neko has is a non-negative number initially, but it can become negative number when jumping.oop
Inputthis
The first line contains only one integer T(T≤50), which indicates the number of test cases.
For each test case, the first line contains four integers n,s,m,k(1≤n≤104,1≤s≤1018,1≤m≤109,1≤k≤n).
The next line contains n integers, the i−th integer is ai−1(−109≤ai−1≤109)spa
Output.net
For each test case, output one line "Case #x: y", where x is the case number (starting from 1) and y is the answer.code
Sample Inputip
2 3 10 5 2 3 2 1 5 20 6 3 2 3 2 1 5get
Sample Outputit
Case #1: 0 Case #2: 2
題意:給你n個數排列成環(你能夠任選一個點做爲起點),你最多跳m次,每次跳k個數。跳到一個數就加上這個數字(能夠屢次跳這個數),求最後最大能獲得的值是多少。若是大於s輸出0,不然輸出s-你的最大值。
思路:找尋環節+長度不超過L的最大子段和。首先用若干個vector存每一個循環節的元素。而後對於每一個循環節,咱們分兩種狀況討論:假設循環節長度爲sz,循環節總和爲sum
一、m不能整除sz。則先計算長度不超過m%sz的最大子段和。而後加上(m/sz)*sum。(在紙上畫一下,好好想一想)
二、m能整除sz。此時若是按第一種狀況考慮的話就至關於固定從第一個點開始跳一直跳完正好(m/sz)個循環節。
因此咱們不必定要從第一個點開始跳。因而先求一下長度不超過sz的最大子段和(至關於找一個起點),再加上((m/sz)-1)*sum。(其實咱們能使它最大化的地方就是起跳的地方到sz和當前循環節第一個位置到停的地方那兩段距離)
而後兩種取個最大值就好了。能夠直接同時計算兩種狀況,至關於不能整除的時候最後剩餘的幾步就不用跳了,整除的時候第一種狀況餘數爲0。
有疑問的地方,歡迎評論區留言。
代碼:
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=2e4+10; ll n,m,s,k,len,p; ll ans,tmp,cnt,ct,tp,f; vector<ll>vc[maxn]; ll a[maxn],q[maxn],stk[maxn],sum[maxn]; bool vis[maxn]; ll cal(vector<ll>&v,ll tmp) { ll res=0; ll nn=v.size(); ll he=0,ta=0; for(ll i=0;i<nn;i++) q[i+nn]=q[i]=a[v[i]]; nn*=2; for(ll i=0;i<nn;i++) { if(i==0)sum[i]=q[i]; else sum[i]=sum[i-1]+q[i]; if(i<tmp) res=max(res,sum[i]);//注意我註釋的這幾個地方,都曾經寫錯過 while(he<ta&&stk[he]+tmp<i) he++; if(he<ta)res=max(res,sum[i]-sum[stk[he]]);// while(he<ta&&sum[stk[ta-1]]>=sum[i]) ta--; stk[ta++]=i;// } return res; } ll go(vector<ll>&v,ll m) { ll sz=v.size(); ll sm=0; for(ll i=0;i<sz;i++) sm+=a[v[i]]; //cout<<"%"; ll len1=m/sz,len2=m%sz; //cout<<"*"; ll m1=cal(v,len2); ll m2=cal(v,sz); m1+=max((ll)0,sm)*len1; m2+=max((ll)0,sm)*((len1>=1)?(len1-1):0); return max(m1,m2); } int main() { int T,cas=1; scanf("%d",&T); while(T--) { scanf("%lld%lld%lld%lld",&n,&s,&m,&k); for(int i=0;i<n;i++) { vis[i]=false; vc[i].clear(); scanf("%lld",&a[i]); } cnt=-1; ans=0; for(ll i=0;i<n;i++) if(!vis[i]){ cnt++; vis[i]=1; vc[cnt].push_back(i); for(ll j=(i+k)%n;(j!=i)&&(!vis[j]);j=(j+k)%n) { vis[j]=1; vc[cnt].push_back(j); } ans=max(ans,go(vc[i],m)); //cout<<ans<<endl; } if(ans>s) ans=0; else ans=s-ans; printf("Case #%d: %lld\n",cas++,ans); } return 0; }
本文分享 CSDN - LSD20164388。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。