AtCoder-agc049_d

做这道题的时候首先发现了是个前缀和,但是不懂为什么没好好观察这个东西是个凹,不然的话这个题对我来说应该是很好去做的,还有这个根号性质也得基于这个上面,回滚背包并不是很会,抽空得学。


把这个式子变一下易知 \(b_i\le b_{i+1}\) 也就是差分单调递增,然后我们发现他是一个谷,所以我们可以枚举这个谷设其为 \(p\) 便可以把原问题换成两半。

然后我们还能发现对于最小的无变化的增长方案,当且仅当是全体 \(+1\) 或者对于一边加上 \(1,2,3,...\) 执行任意操作显然都可以行如何证明这个东西是可以通到所有操作的呢,这里就用到差分数组了,倘若我们这么加,那么 \([i,n]\) 的所有差分只会 \(+1\) 故得证。

所以这个操作是可以推广全局的。

但是这个东西算的话是 \(O(n^2\sqrt{m})\) 的,回滚背包一下就行。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
// #define int ll
template <typename T>
T inv(const T& x, const T& y) {
    assert(x != 0);
    T u = 0, v = 1, a = x, m = y, t;
    while (a != 0) {
        t = m / a;
        swap(a, m -= t * a);
        swap(u -= t * v, v);
    }
    assert(m == 1);
    return u;
}

template <typename T>
class Modular {
public:
    using Type = typename decay<decltype(T::value)>::type;

    constexpr Modular() : value() {}
    template <typename U> Modular(const U& x) { value = normalize(x); }

    template <typename U>
    static Type normalize(const U& x) {
        Type v = static_cast<Type>((-mod() <= x && x < mod()) ? x : x % mod());
        if (v < 0) v += mod();
        return v;
    }

    const Type& operator()() const { return value; }
    template <typename U> explicit operator U() const { return static_cast<U>(value); }
    constexpr static Type mod() { return T::value; }

    Modular& operator+=(const Modular& other) {
        if ((value += other.value) >= mod()) value -= mod();
        return *this;
    }
    Modular& operator-=(const Modular& other) {
        if ((value -= other.value) < 0) value += mod();
        return *this;
    }
    template <typename U> Modular& operator+=(const U& other) { return *this += Modular(other); }
    template <typename U> Modular& operator-=(const U& other) { return *this -= Modular(other); }
    Modular& operator++() { return *this += 1; }
    Modular& operator--() { return *this -= 1; }
    Modular operator++(int) {
        Modular result(*this);
        *this += 1;
        return result;
    }
    Modular operator--(int) {
        Modular result(*this);
        *this -= 1;
        return result;
    }
    Modular operator-() const { return Modular(-value); }

    template <typename U = T>
    typename enable_if<is_same<typename Modular<U>::Type, int>::value, Modular>::type& operator*=(const Modular& rhs) {
#ifdef _WIN32
        uint64_t x = static_cast<int64_t>(value) * static_cast<int64_t>(rhs.value);
        uint32_t xh = static_cast<uint32_t>(x >> 32), xl = static_cast<uint32_t>(x), d, m;
        asm(
            "divl %4; \n\t"
            : "=a"(d), "=d"(m)
            : "d"(xh), "a"(xl), "r"(mod()));
        value = m;
#else
        value = normalize(static_cast<int64_t>(value) * static_cast<int64_t>(rhs.value));
#endif
        return *this;
    }
    template <typename U = T>
    typename enable_if<is_same<typename Modular<U>::Type, long long>::value, Modular>::type& operator*=(const Modular& rhs) {
        long long q = static_cast<long long>(static_cast<long double>(value) * rhs.value / mod());
        value = normalize(value * rhs.value - q * mod());
        return *this;
    }
    template <typename U = T>
    typename enable_if<!is_integral<typename Modular<U>::Type>::value, Modular>::type& operator*=(const Modular& rhs) {
        value = normalize(value * rhs.value);
        return *this;
    }

    Modular& operator/=(const Modular& other) { return *this *= Modular(inv(other.value, mod())); }

    friend const Type& abs(const Modular& x) { return x.value; }
    template <typename U> friend bool operator==(const Modular<U>& lhs, const Modular<U>& rhs);
    template <typename U> friend bool operator<(const Modular<U>& lhs, const Modular<U>& rhs);
    template <typename V, typename U> friend V& operator>>(V& stream, Modular<U>& number);

private:
    Type value;
};

template <typename T> bool operator==(const Modular<T>& lhs, const Modular<T>& rhs) { return lhs.value == rhs.value; }
template <typename T, typename U> bool operator==(const Modular<T>& lhs, U rhs) { return lhs == Modular<T>(rhs); }
template <typename T, typename U> bool operator==(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) == rhs; }

template <typename T> bool operator!=(const Modular<T>& lhs, const Modular<T>& rhs) { return !(lhs == rhs); }
template <typename T, typename U> bool operator!=(const Modular<T>& lhs, U rhs) { return !(lhs == rhs); }
template <typename T, typename U> bool operator!=(U lhs, const Modular<T>& rhs) { return !(lhs == rhs); }

template <typename T> bool operator<(const Modular<T>& lhs, const Modular<T>& rhs) { return lhs.value < rhs.value; }

template <typename T> Modular<T> operator+(const Modular<T>& lhs, const Modular<T>& rhs) { return Modular<T>(lhs) += rhs; }
template <typename T, typename U> Modular<T> operator+(const Modular<T>& lhs, U rhs) { return Modular<T>(lhs) += rhs; }
template <typename T, typename U> Modular<T> operator+(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) += rhs; }

template <typename T> Modular<T> operator-(const Modular<T>& lhs, const Modular<T>& rhs) { return Modular<T>(lhs) -= rhs; }
template <typename T, typename U> Modular<T> operator-(const Modular<T>& lhs, U rhs) { return Modular<T>(lhs) -= rhs; }
template <typename T, typename U> Modular<T> operator-(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) -= rhs; }

template <typename T> Modular<T> operator*(const Modular<T>& lhs, const Modular<T>& rhs) { return Modular<T>(lhs) *= rhs; }
template <typename T, typename U> Modular<T> operator*(const Modular<T>& lhs, U rhs) { return Modular<T>(lhs) *= rhs; }
template <typename T, typename U> Modular<T> operator*(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) *= rhs; }

template <typename T> Modular<T> operator/(const Modular<T>& lhs, const Modular<T>& rhs) { return Modular<T>(lhs) /= rhs; }
template <typename T, typename U> Modular<T> operator/(const Modular<T>& lhs, U rhs) { return Modular<T>(lhs) /= rhs; }
template <typename T, typename U> Modular<T> operator/(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) /= rhs; }

template <typename T, typename U>
Modular<T> qpow(const Modular<T>& a, const U& b) {
    assert(b >= 0);
    Modular<T> x = a, res = 1;
    for (U p = b; p; x *= x, p >>= 1)
        if (p & 1) res *= x;
    return res;
}

template <typename T> bool IsZero(const Modular<T>& number) { return number() == 0; }
template <typename T> string to_string(const Modular<T>& number) { return to_string(number()); }

// U == std::ostream? but done this way because of fastoutput
template <typename U, typename T> U& operator<<(U& stream, const Modular<T>& number) { return stream << number(); }

// U == std::istream? but done this way because of fastinput
template <typename U, typename T>
U& operator>>(U& stream, Modular<T>& number) {
    typename common_type<typename Modular<T>::Type, long long>::type x;
    stream >> x;
    number.value = Modular<T>::normalize(x);
    return stream;
}

// using ModType = int;
// struct VarMod { static ModType value; };
// ModType VarMod::value;
// ModType& mod = VarMod::value;// for mod can change
// using Mint = Modular<VarMod>;

constexpr int mod = (int)1e9 + 7; 
using Mint = Modular<std::integral_constant<decay<decltype(mod)>::type, mod>>;

struct Fact {
    vector<Mint> fac, ifac;
    const int n;
    Fact(const int& _n) : n(_n), fac(_n + 1, Mint(1)), ifac(_n + 1) {
        for (int i = 1; i <= n; ++i) fac[i] = fac[i - 1] * i;
        ifac[n] = inv(fac[n](), mod);
        for (int i = n; i; --i) ifac[i - 1] = ifac[i] * i;
    }
    Mint C(const int& n, const int& k) {
        if (n < 0 || k < 0 || n < k) return 0;
        return fac[n] * ifac[k] * ifac[n - k];
    }
    Mint A(const int& n, const int& k) {
        if (n < 0 || k < 0 || n < k) return 0;
        return fac[n] * ifac[n - k];
    }
};

const int inf = 0x3f3f3f3f;
char buf[1 << 21], *p1 = buf, *p2 = buf;
#define scin static inline
typedef vector<int> vi;
typedef unsigned long long ull;
typedef pair<int ,int> pii;
typedef pair<ll, ll> pll;
#define gc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
#define getchar() gc()
template <typename T> scin void rd(T& s) {
    s = 0; char ch = getchar(); bool fu = 0;
    while (ch < '0' || ch > '9') ch == '-' ? fu = 1 : 0, ch = getchar();
    while (ch >= '0' && ch <= '9') s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
    s = fu ? -s : s;
}

template <typename T, typename...Args> scin void rd(T& s, Args& ...args) {rd(s), rd(args...);}
template <typename T> scin bool updmin(T& a,T& b) {return a > b ? a = b, true : false;}
template <typename T> scin bool updmax(T& a,T& b) {return a < b ? a = b, true : false;}
template <typename T> scin void updmod(T& a) {a >= mod ? a -= mod : 0;}
template <typename T> scin T updmod(T a,T b) {return a + b >= mod ? a + b - mod : a + b;}

const int N = 1e6 + 10;
ll n, m;
Mint f[N], ans;

void Solve() {
	rd(n, m);
	f[0] = 1;
	for (ll i = 1; i < n && i * (i + 1) / 2 <= m; ++i)
		for (ll j = i * (i + 1) / 2; j <= m; ++j)
			f[j] += f[j - i * (i + 1) / 2];
	for (ll i = n; i <= m; ++i) f[i] += f[i - n];
	for (ll i = 1; i <= n; ++i) {
		if (i * (i - 1) / 2 <= m) ans += f[m - i * (i - 1) / 2];
		if ((n - i) * (n - i + 1) / 2 <= m)
			for (int j = m; j >= (n - i) * (n - i + 1) / 2; --j)
				f[j] -= f[j - (n - i) * (n - i + 1) / 2];
		if (i * (i + 1) / 2 <= m)
			for (int j = i * (i + 1) / 2; j <= m; ++j)
				f[j] += f[j - i * (i + 1) / 2];
	}
	cout << ans << "\n";
}

signed main() {
    // freopen("input.in", "r", stdin);
    // ios::sync_with_stdio(false);
    // cin.tie(0), cout.tie(0);
    int T = 1;
    // rd(T);
    while (T--) Solve();
    return 0;
}
posted @ 2026-07-24 23:10  static_inline  阅读(7)  评论(0)    收藏  举报