洛谷-P6686 混凝土數學

題目描述:這裏c++

思路:git

1、部分分算法算法

  • 對於的數據,用暴力解決便可,時間複雜度
  • 對於另外的數據(全部木棍長度相等),考慮用組合數學,答案爲

 2、正解優化

咱們考慮對整個序列進行桶排序spa

咱們設每一個數出現的次數爲code

  • 對於全部的數,加上比它小的全部數出現的次數,並加上這個數至這個數中全部數出現的個數。
  • 特別的,對於全部的數,須要再次加上

可是,咱們會發現這依然過不了(TLE了一個點)。blog

 

咱們再次仔細觀察正解的統計方式第一條,發現這能夠用前綴和優化。排序

因而,這道題就作完了。get

 

下面附上代碼:數學

#include <bits/stdc++.h>
using namespace std;

template < typename T > void read(T &x)
{
    int f = 1;x = 0;char c = getchar();
    for (;!isdigit(c);c = getchar()) if (c == '-') f = -f;
    for (; isdigit(c);c = getchar()) x = x * 10 + c - '0';
    x *= f;
}

const long long mod = 998244353;
int a[200005];
long long bin[200005];
long long sum[200005];

int main()
{
    //freopen(".in", "r", stdin);
    //freopen(".out", "w", stdout);
    int n, binmax = INT_MIN;
    long long ans = 0;
    read(n);
    for(int i = 1;i <= n;i++)
    {
        read(a[i]);
        bin[a[i]]++;
        binmax = max(binmax, a[i]);
    }
    int t = a[1];
    int flag = 1;    
    for(int i = 2;i <= n;i++)
        if(a[i] != t)
        {
            flag = 0;
            break;
        }
    if(flag)
    {
        long long ans = 1;
        for(int i = n;i > n - 3;i--)
        {
            ans *= i;
        }
        cout << (ans / 6) % mod << endl;
        return 0;
    }
    if(n <= 200)
    {
        for(int i = 1;i <= n;i++)
            for(int j = i + 1;j <= n;j++)
                for(int k = j + 1;k <= n;k++)
                    if((a[i] == a[j] || a[i] == a[k] || a[j] == a[k]) && (a[i] + a[j] > a[k]) && a[i] + a[k] > a[j] && a[j] + a[k] > a[i])
                        ans++;
        cout << ans % mod << endl;
        return 0;
    }
    sum[0] = 0;
    for(int i = 1;i <= binmax;i++)
        sum[i] = bin[i] + sum[i - 1];
    long long front = 0;
    for(int i = 1;i <= binmax;++i)
        if(bin[i])
        {
            if(bin[i] >= 3)
            {
                long long ansj = 1;
                for(int j = bin[i];j > bin[i] - 3;--j)
                    ansj *= j;
                ans += ansj / 6;
                ans %= mod;
            }
            if(bin[i] >= 2)
            {
                long long tx = bin[i] * (bin[i] - 1) / 2;
                ans += front * tx;
                ans %= mod;
                long long up = min(i * 2, binmax + 1) - 1;
                long long ty = sum[up] - sum[i];
                ans += ty * tx;
                ans %= mod;
            }
            front += bin[i];
        }
    cout << ans << endl;
    return 0;
}
相關文章
相關標籤/搜索