CodeForces - 1362E Johnny and Grandmaster(贪心+模拟)
題目鏈接:點(diǎn)擊查看
題目大意:給出一個(gè)基數(shù) p ,再給出 n 個(gè)指數(shù) k ,換句話說,現(xiàn)在有一個(gè)長度為 n 的序列,每個(gè)元素都是 p^k[ i ] ,現(xiàn)在需要將這個(gè)序列分到兩個(gè)集合中,使得兩個(gè)集合元素和之差的絕對(duì)值最小,輸出這個(gè)絕對(duì)值
題目分析:首先需要知道的是,題意給出了基數(shù)和指數(shù),換句話說所有的數(shù)字都是在 p 進(jìn)制下進(jìn)行的,因?yàn)橹霸?cf 上也做過一個(gè)類似的題,就是讓最大的單獨(dú)一組,剩下最小的都在一組是最優(yōu)的,而在這個(gè)題目中,可以先對(duì)指數(shù)進(jìn)行降序排序,設(shè)答案為 ans,初始時(shí)為 0 ,一個(gè)顯然的貪心策略是:
因?yàn)樗械那闆r都是在 p 進(jìn)制下進(jìn)行的,所以每次操作的 ans 保證了一定是非負(fù)的,這樣貪心去模擬就好了
其實(shí)這個(gè)題目的難點(diǎn)是在于模擬上,而不是前面的貪心,因?yàn)槊總€(gè)元素都非常大,顯然是無法直接維護(hù)這個(gè) ans ,但是我們發(fā)現(xiàn),只需要判斷 ans 是否為 0 即可,所以這里可以偷個(gè)懶,利用雙哈希取模,這樣就可以判斷 ans 是否為 0 了,不過常用的一些哈希值很容易被作者想到,從而出一些針對(duì)的數(shù)據(jù),所以我選了一個(gè)比較不錯(cuò)的 mod = 999999998
然后說一下正解,因?yàn)樗械臄?shù)都是基于 p 進(jìn)制下的,舉個(gè)例子就能講清楚了,假設(shè)此時(shí)的 p = 4 ,而最大的 k 是 100 ,第一步操作 ans = 0,執(zhí)行操作 1 ,所以此時(shí) ans = 4^100,接下來需要一個(gè) 4^100 來中和 ans ,或者 4 個(gè) 4^99 來中和,或者 16 個(gè) 4^98,因?yàn)槲覀円呀?jīng)排好序了,如果接下來的一個(gè)數(shù)時(shí) 4^99 的話,那么執(zhí)行操作 2 中和結(jié)束后,得到的是:ans = 3 * 4^99,換句話說,此時(shí)還需要 3 個(gè) 4^99,或者需要 12 個(gè) 4^98 ....以此類推,這樣我們只需模擬上述過程即可
注意一個(gè)小細(xì)節(jié),就是對(duì)應(yīng)著樣例的第三個(gè),那就是第一個(gè) k = 100 ,而第二個(gè) k = 1,中間跨過了 99 個(gè) k ,此時(shí)為了中和一開始的 5^100,需要 5^99?個(gè) 5^1 來中和,顯然 5^99 也過于龐大了,所以需要增加一個(gè)對(duì)應(yīng)的剪枝,那就是如果當(dāng)前需要中和的個(gè)數(shù)比數(shù)據(jù)范圍 1e6 還大,那剩下的所有數(shù)肯定都用來中和是最優(yōu)的,同時(shí)因?yàn)?2^20 > 1e6,所以每次更新需要中和的個(gè)數(shù)的時(shí)候,至多到 20 就足夠了
代碼:
正解
#include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e6+100;const int mod=1e9+7;int k[N];LL q_pow(LL a,LL b) {LL ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod;b>>=1;}return ans; }int main() { #ifndef ONLINE_JUDGE // freopen("input.txt","r",stdin); // freopen("output.txt","w",stdout); #endif // ios::sync_with_stdio(false);int w;cin>>w;while(w--){int n,p;scanf("%d%d",&n,&p);for(int i=1;i<=n;i++)scanf("%d",k+i);sort(k+1,k+1+n,greater<int>());LL ans=0,remain=0;bool flag=false;k[0]=k[1];for(int i=1;i<=n;i++){if(k[i]!=k[i-1]){int t=min(k[i-1]-k[i],20);assert(t>0);while(t--){remain*=p;if(remain>N){flag=true;break;}}}if(remain>0||flag){remain--;ans=(ans-q_pow(p,k[i])+mod)%mod;}else{remain++;ans=(ans+q_pow(p,k[i]))%mod;}}printf("%lld\n",ans);}return 0; }哈希:
#include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e6+100;const int mod1=1e9+7;const int mod2=999999998;int k[N];LL q_pow(LL a,LL b,LL mod) {LL ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod;b>>=1;}return ans; }int main() { #ifndef ONLINE_JUDGE // freopen("input.txt","r",stdin); // freopen("output.txt","w",stdout); #endif // ios::sync_with_stdio(false);int w;cin>>w;while(w--){int n,p;scanf("%d%d",&n,&p);for(int i=1;i<=n;i++)scanf("%d",k+i);sort(k+1,k+1+n,greater<int>());LL ans1=0,ans2=0;for(int i=1;i<=n;i++){if(!ans1&&!ans2){ans1=(ans1+q_pow(p,k[i],mod1))%mod1;ans2=(ans2+q_pow(p,k[i],mod2))%mod2;}else{ans1=(ans1-q_pow(p,k[i],mod1)+mod1)%mod1;ans2=(ans2-q_pow(p,k[i],mod2)+mod2)%mod2;}}printf("%lld\n",ans1);}return 0; }?
總結(jié)
以上是生活随笔為你收集整理的CodeForces - 1362E Johnny and Grandmaster(贪心+模拟)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CodeForces - 1363E T
- 下一篇: 牛客 - Sumo and Easy S