zoukankan      html  css  js  c++  java
  • 「TJOI 2018」教科书般的亵渎

    「TJOI 2018」教科书般的亵渎

    题目描述

    小豆喜欢玩游戏,现在他在玩一个游戏遇到这样的场面,每个怪的血量为 (a_i) ,且每个怪物血量均不相同, 小豆手里有无限张“亵渎”。
    亵渎的效果是对所有的怪造成 (1) 点伤害,如果有怪死亡,则再次施放该法术。我们认为血量为 (0) 的怪物死亡。
    小豆使用一张“亵渎”会获得一定的分数,分数计算如下,在使用一张“亵渎”之后,每一个被亵渎造成伤害的怪会产生 (x^k) ,其中 (x) 是造成伤害前怪的血量为 (x) 和需要杀死所有怪物所需的“亵渎”的张数 (k)

    (N leq 1000, K leq 15)

    解题思路 :

    考虑将没有出现的血量集合 (m_i) 从小到大排序,观察发现对于每一个 (m_i) ,其会使得所有血量 (-m_i)

    设此时场上的最大血量为 (c) ,那么其能产生的贡献就是 ((sum_{j=1}^{c} j^k) - sum_{j=i}^{m} m_i ^k)

    由于 (m) 很小,计算后面式子的复杂度可以忽略不计,问题就转化为快速计算前面的式子

    观察发现前面的式子其实就是一个 (k + 1) 次的多项式,暴力插值求解即可


    /*program by mangoyang*/
    #include<bits/stdc++.h>
    #define inf (0x7f7f7f7f)
    #define Max(a, b) ((a) > (b) ? (a) : (b))
    #define Min(a, b) ((a) < (b) ? (a) : (b))
    typedef long long ll;
    using namespace std;
    template <class T>
    inline void read(T &x){
    	int f = 0, ch = 0; x = 0;
    	for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
    	for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
    	if(f) x = -x;
    }
    #define int ll
    const int Mod = 1000000007;
    vector<int> x, y;
    int a[105], n, m;
    inline int Pow(int a, int b){
    	int ans = 1; a %= Mod;
    	for(; b; b >>= 1, a = a * a % Mod)
    		if(b & 1) ans = ans * a % Mod;
    	return ans;
    }
    inline void Prework(int k){
    	x.clear(), y.clear();
    	for(int i = 1, now = 0; i <= k + 2; i++) 
    		x.push_back(i), y.push_back((now += Pow(i, k)) %= Mod);
    }
    inline int calc(int now){
    	int res = 0;
    	for(int i = 0; i < x.size(); i++){
    		int tmp = y[i];
    		for(int j = 0; j < x.size(); j++) if(j != i) 
    			(tmp *= (now - x[j]) % Mod * Pow(x[i] - x[j], Mod - 2) % Mod) %= Mod;
    		(res += tmp) %= Mod;
    	}
    	return res;
    }
    inline void solve(){
    	int ans = 0, now = 0;
    	read(n), read(m), Prework(m + 1);
    	for(int i = 1; i <= m; i++) read(a[i]);
    	sort(a + 1, a + m + 1);
    	for(int i = 1; i <= m; i++){
    		(ans += calc(n - now)) %= Mod;
    		for(int j = i; j <= m; j++) (ans -= Pow(a[j] - now, m + 1)) %= Mod;
    		now = a[i];
    	}
    	(ans += calc(n - now)) %= Mod;
    	cout << ((ans % Mod) + Mod) % Mod << endl;
    }
    signed main(){
    	int T; read(T); while(T--) solve();
    	return 0;
    }
    
  • 相关阅读:
    C++ 四种cast 用法
    Wannafly挑战赛1 B Xorto
    python里的闭包
    编译器对类的编译顺序
    class和struct
    typedef类型别名
    decltype类型指示符
    左值和右值
    const限定符
    hdu5678 树上第k小
  • 原文地址:https://www.cnblogs.com/mangoyang/p/9445607.html
Copyright © 2011-2022 走看看