1. 程式人生 > >SSL 2676_數學_模擬

SSL 2676_數學_模擬

har sin 都是 一個 spa mes 快速冪 div getchar

題目描述

小A得到了一個數列A,他告訴你這個數列中所有的A[i]都是1到n的自然數,並且告訴你對於一些A[i]不能取哪些值。無聊的你想要知道所有可能的數列的積的和。定義一個數列的積為這個數列所有數的乘機。由於答案太大,只要模10^9+7輸出即可。


思路

首先有一個規律就是ans為每一項中沒有被限制的數相加讓後相乘

顯然這樣直接暴力會T,數據中的限制有 $10^5$ 個,而總數則有$10^9$ 個

所以沒有限制條件的數量還是很多的,我們就可以用一個快速冪加上暴力來求解


#include <stdio.h>
#include <algorithm>
#include <iostream>
using
namespace std; #define p 1000000007 #define maxn 100001 struct arr { long long x, y; }a[maxn]; long long tot; long long read() { long long x = 0; char ch = getchar(); while (ch < 0 || ch > 9) ch = getchar(); while (ch >= 0 && ch <= 9) {x = (x << 1) + (x << 3
) + ch -0; ch = getchar();} return x; } long long cmp(arr a, arr b) { return (a.x < b.x) || (a.x == b.x && a.y < b.y); } long long fast(long long x) { if (x == 0) return 1; if (x == 1) return tot; long long t = fast(x / 2) % p; if (x % 2 == 1) return (((t * t) % p) * (tot % p)) % p;
else return (t * t) % p; } int main() { long long n, m ,k; cin >> n >> m >> k; for (long long i = 1; i <= k; i++) { a[i].x = read(); a[i].y = read(); } sort(a + 1, a + k + 1, cmp); for (long long i = 1; i < k; i++) if (a[i].x == a[i + 1].x && a[i].y == a[i + 1].y) a[i].y = 0; tot = ((1 + n) * n) / 2; long long i = 0, ans = 1, now = 1, sum = m; while (i < k) { i++; if (a[i].x != a[i - 1].x) { ans = (ans * (now % p)) % p; sum--; now = tot; } if (a[i].y != 0) now -= a[i].y; } ans = (ans * (now % p)) % p; ans = (ans * fast(sum)) % p; cout << ans << endl; }

SSL 2676_數學_模擬