QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#510040#7662. Kaldorian KnightsPonyHexWA 1ms7856kbC++146.5kb2024-08-08 20:46:402024-08-08 20:46:40

Judging History

你现在查看的是最新测评结果

  • [2024-08-08 20:46:40]
  • 评测
  • 测评结果:WA
  • 用时:1ms
  • 内存:7856kb
  • [2024-08-08 20:46:40]
  • 提交

answer

#define _CRT_SECURE_NO_WARNINGS 1
#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
#include<random>
#include <chrono>
using namespace std;
std::mt19937_64 rng((std::chrono::steady_clock::now().time_since_epoch().count()));
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define RND mt19937 rnd(0xab8d5f6);
#define time_while(time_while_val) while (((double)clock() - start) / clocks_per_sec < time_while_val)
//#define time_while(time_while_val) while ((double)clock() / clocks_per_sec < time_while_val)//弃
#define rep1(i, n) for(long long i = 1; i <= n; ++i)
#define rep0(i, n) for(long long i = 0; i <= n; ++i)
#define double long double
//#define int long long
//#define ll unsigned long long
#define lc u<<1
#define rc u<<1|1
#define endl "\n"
#define X first
#define Y second
typedef long long ll;
//typedef unsigned long long ull;
typedef pair<int, int> PII;
double PI = acos(-1.0);
const double eps = 1e-9;
const ll maxn = 1e6 + 5;
const ll maxm = 2e18;
const ll inf = 2147483647;
const ll mod = 1e9+7;
const int dx[] = { 1,0,-1,0,1,1,-1,-1 };//前4为邻
const int dy[] = { 0,-1,0,1,-1,1,-1,1 };

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch>'9')
    {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
        x = x * 10 + ch - '0', ch = getchar();
    return x * f;
}
int gcd(int a, int b) {
    return b ? gcd(b, a % b) : a;
}
ll ksm(ll a, ll b) {
    ll ans = 1;
    ll base = a;
    while (b) {
        if (b & 1)ans = ans * base % mod;
        base = base * base % mod;
        b >>= 1;
    }
    return ans % mod;
}
ll getinv(ll a) {
    return ksm(a, mod - 2);
}
void debug(ll ans) {
    cout << "业师大人帮你检查答案:" << ans << endl;
}

/*
ll getinv(ll a) {
    return ksm(a, mod - 2);
}*/

//dismyth
//警钟长鸣

/*2024/8/6
待补:cdq分治补不出来,三维偏序,平衡树->link cut tree*/
/*待补 324(包括f),310,313,315,317*///好多,但是每天得vp,强度得上去
/*306d,344d*/
//赛时多出,赛后少补
//vp一把


/*
struct cmp {
    bool operator()(pair<ll, ll> a, pair<ll, ll>  b) {
        return a.X > b.X;//表示小根堆
    }
};*/

//异或是可叠加的,所以异或是可求前缀和的
//注意map初始化为0遇到ans为0时记忆化会失效,这时候我们就要用到.count
//re.count({l,r})

ll n, m;
ll k[maxn];
ll A[maxn];
ll f[maxn];

//RND;
void solve() {
    //继续补,组合数学,必须补出来
    //然后强化dp
    cin >> n >> m;
    k[0] = 0;
    for (int i = 1; i <= m; i++) {
        cin >> k[i];
        k[i] += k[i - 1];
    }
    //首先,这里看不懂,为什么,对k要获取前缀和
    A[0] = 1;
    for (int i = 1; i <= n; i++) {
        A[i] = A[i - 1] * i;
    }
    /*
    for (int i = 1; i <= m; i++) {
        d[i] = A[k[i]];
        for (int j = 1; j < i; j++) {
            d[i] = ((d[i] - A[k[i] - k[j]] * d[j] % mod) + mod) % mod;

        }
    }
    int ans = A[n];
    for (int i = 1; i <= m; i++) {
        ans = ((ans - A[n - k[i]] * d[i] % mod) + mod) % mod;
    }
    cout << ans;*/
    //上面那段完全看不懂,旁边还一直有生物在扭动

    ///懂了,题解很好,扭动也没办法影响我,首先,这篇题解让我减轻了一直以来对于组合数的畏惧
    //因为组合数总是会取模,总是会导致暴ll,这样原本的元素无法完全的保存
    //我知道在模运算下的除法可以使用逆元代替,加法,乘法,可以在模运算下叠加
    //减法,本来也可以叠加,但是会减没(),这是出错点,(我察觉到了出错点,但是没想到解决办法),可能见过但忘了()
    //现在都回来了,直接组合数学大成,完全之龙了

    //知道组合数的运算了,那推导不是轻轻松松
    //首先我们从头开始看,我们发现,首先,总情况数为A[n]
    //对于第一家族,不合理的情况显然为A[k1]*A[n-k1]
    //对于k2来说不合理的情况按理来说是A[k2]*A[n-k2]
    //但是我们很快发现,k2的不合理情况与k1的不合理情况存在重叠
    //具体就是,1都老老实实在最后的情况
    //我们将重叠的情况从k2中分离出来,然后我们就能发现
    //A[k1]*A[k2]*A[n-k2],两者在这一部分重叠
    //再向后会怎么样?,我们可以很容易地发现,重叠部分应为A[k1]*A[k2]*A[k3]*A[n-k3]
    //所以说在ki处重叠的方案数应为A[k1]*...*A[ki]*A[n-ki]//哦哦抱歉这里最后面的n-ki其中ki应表示前缀和
    //
    //推导结束,我们其实只走一遍加上,走一遍减去即可

    //错了,呱!怎么可能
    //因为推导是不对的,不能单纯消去相邻的位置的重叠部分,我们如果面向k1与k3
    //我们就能发现,k1与k3同样是重叠的
    //
    //反正,感觉写的不好,重开
    /*
    ll ans = 0;
    for (int i = 1; i <= m; i++) {
        ans += ((A[k[i]]) * A[n - k[i]])%mod;
        ans %= mod;
    }
    ll ex = A[k[1]];
    for (int i = 2; i <= m; i++) {
        ex *= A[k[i] - k[i - 1]];
        ex %= mod;
        ans += mod;
        ans -= (ex * A[n - k[i]])%mod;
        ans %= mod;
    }
    cout << ans << endl;
    cout << A[n] << endl;
    cout << (A[n] + mod - ans)%mod << endl;*/
    //我们直接取A[km]*A[n]是否直接就是不行的情况
    //显然不是,因为在框定ki时其中的非贵族骑士可以放置在任意位置
    //如果我们先放置k1,那么对于剩下的元素,其实囊括了大量的情况
    //对于k2,我们在放置的时候应该避开11111的情况
    //对于k3我们则应该避开21都放置在最后两个位置的情况
    //这其实就是,我们尝试放置k2时的情况,不,应该是我们尝试放置k2并且没有去掉k1时的
    if (m == 0) {
        cout << A[n] << endl; return;
    }
    ll ans = A[k[1]]*A[n-k[1]];
    for (int i = 2; i <= m; i++) {
        ans += (A[k[i]] * A[n - k[i]])%mod;
        ans += mod;
        ans -= (A[n - k[i]] * A[k[i] - k[i - 1]] * A[k[i - 1]]);
        ans %= mod;
    }
    //感觉没有问题了,怎么还是错啊
    cout << (A[n] + mod - ans) % mod << endl;
    //我要碎了
    return;
}


signed main() {
    IOS;
    ll t = 1;
    //cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}

/*致我已死的友人*/
/*PonyHex*/


Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 1ms
memory: 7680kb

input:

3 0

output:

6

result:

ok single line: '6'

Test #2:

score: 0
Accepted
time: 1ms
memory: 7724kb

input:

4 1
3

output:

18

result:

ok single line: '18'

Test #3:

score: 0
Accepted
time: 1ms
memory: 7716kb

input:

4 2
2
1

output:

16

result:

ok single line: '16'

Test #4:

score: 0
Accepted
time: 1ms
memory: 7744kb

input:

10 1
10

output:

0

result:

ok single line: '0'

Test #5:

score: -100
Wrong Answer
time: 1ms
memory: 7856kb

input:

10 10
1
1
1
1
1
1
1
1
1
1

output:

999481607

result:

wrong answer 1st lines differ - expected: '0', found: '999481607'