牛客網編程題 小遊戲 數學式子展開優化

在這裏插入圖片描述
在這裏插入圖片描述

題解:

這題暴力O(n2)是會超時的,所以我們要進行優化。
我們首先把元素按下標分爲奇數和偶數兩組,然後再把標記相同的細分爲一組,因爲題目要求每次走正偶數步,所以奇數組的元素是可以相互得到的,偶數組的元素是可以相互得到的。
然後就是組內求和,在這一步我們可以將O(n2)優化爲O(n),看個例子:

在這裏插入圖片描述
我們完全可以在O(n)的時間內求出Q的和,當然這裏也可以求a的和,是一樣的,然後就是圖中畫圈的那一項,不難發現是(n-2)* aiQi,於是我們再遍歷一次,時間也是O(n),把這些項加上,這樣組內求和就完成了。
最後把所有組的和加到一起就是答案,注意mod 10007就行了。

代碼如下:

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<cmath>
#include<queue>
#include<string>
#include<string.h>
#include<map>
#include<vector>
#define MAX 100005
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;

ll n,m,mod=10007;
ll Q[MAX];
vector<ll> v1[MAX],v2[MAX];//一個記錄奇數項,一個記錄偶數項

ll cal(vector<ll> t){
    if(t.size()<2) return 0;
    ll ans=0,sum=0;//ans爲總和,sum爲Q的和
    for(int i=0;i<t.size();i++){
        sum+=(Q[t[i]])%mod;
    }
    for(int i=0;i<t.size();i++){
        ans=(ans+t[i]*sum)%mod+t[i]*Q[t[i]]*(t.size()-2)%mod;
    }
    return ans%mod;
}

int main(){
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&Q[i]);
    }
    ll L;
    for(int i=1;i<=n;i++){
        scanf("%lld",&L);
        if(i%2) v1[L-1].push_back(i);//把所有標記爲L的奇數項放入一個集合
        else v2[L-1].push_back(i);//把所有標記爲L的偶數項放入一個集合
    }
    ll sum=0;
    for(int i=0;i<m;i++){
        sum=(sum+cal(v1[i])+cal(v2[i]))%mod;
    }
    printf("%lld",sum);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章