【NOIP2018模擬10.26】總結
阿新 • • 發佈:2018-12-17
T1
這個題考試的時候仔細想想應該可以切掉的。。。
先轉換成計數問題,最後求一下逆元,除以區間個數就ok。 對於的資料,可以按照題意模擬。 對於的資料,觀察到線段樹上每個節點的貢獻獨立,列舉所有節點,一個節點的貢獻是可以計算的。 對於的資料,觀察到線段樹上每一層的貢獻獨立,可以考慮如何求第層對答案的貢獻。 我們先考慮一個節點作為包含左端點的情況,因為它作為包含右端點的情況是和包含左端點一樣的,我們只需要乘以就可以了。
(被算x次意思是在x個區間查詢裡它有貢獻) 在草稿紙上搗鼓幾下可以發現,第層所有的作為左兒子的節點總共要被算次。 所有的作為右兒子的節點被計算的次數如下: 可以發現,第層所有作為右兒子的節點被計算的次數構成了一個首項為1,末項為,項數為 的等差數列。 套用等差數列求和公式,可得到所有右兒子計算次數為: 所以答案可以表示如下: 化簡之後得到: 直接計算這個式子,複雜度
對於的資料,關鍵是這個怎麼算:
於是答案就是:
用快速冪的時間計算答案,模數在int
範圍內,不會爆long long
。
Code:
#include <cstdio>
#include <cstring>
#include <cstdlib>
typedef long long ll;
const ll P = 1e9 + 7;
ll pow(ll a, ll b)
{
a %= P;
ll ret = 1;
while (b)
{
if (b & 1) ret = ret * a % P;
a = a * a % P, b >>= 1;
}
return ret;
}
ll n;
int main()
{
//freopen("A.in", "r", stdin);
//freopen("A.out", "w", stdout);
scanf("%lld", &n);
ll p1 = pow(2, n - 1), p = p1 * 2 % P, p2 = p * 2 % P;
ll sum = (p1 + 1) * ((n - 1) % P * p2 % P + 2) % P;
printf("%lld\n", 2 * sum % P * pow(p, P - 2) % P * pow(p + 1, P - 2) % P);
fclose(stdin);
fclose(stdout);
return 0;
}
T2
大坑待填。
T3
對於的資料,按照題意暴力。 對於的隨機資料,將詢問離線,把每個點向上更新答案。
對於的資料。考慮到各個質因子對答案的影響是獨立的,因此可以分開統計,我們將每個點的和詢問的都分解質因數,將質因數相同放在一起,容易得出其指數是所有指數與詢問取的和。我們可以按照指數排序,這樣對於每個質因子,就是一個三維偏序問題:第一維是序,修改的點要在詢問子樹內,第二維是深度,距離詢問的點必須,第三位是指數,對於小於詢問的指數,我們需要統計它們的和,對於大於詢問的指數,我們只需要知道有多少個就行了。於是cdq分治一下,注意常數,就沒問題了。
Code:
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int N = 1e5 + 7, MAX = 1e7 + 7, P = 998244353;
inline int read()
{
int x = 0, f = 0;
char c = getchar();
for (; c < '0' || c > '9'; c = getchar()) if (c == '-') f = 1;
for (; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ '0');
return f ? -x : x;
}
inline int qpow(int a, int b)
{
int ret = 1;
while (b)
{
if (b & 1) ret = ret * 1ll * a % P;
a = a * 1ll * a % P, b >>= 1;
}
return ret;
}
int n, q, k, x[N], c[N];
struct note { int id, ct; };
vector<note> incl[MAX / 10];
int tot, tt, st[N], to[N << 1], nx[N << 1], dfn[N], out[N], dep[N], a[N];
void add(int u, int v) { to[++tot] = v, nx[tot] = st[u], st[u] = tot; }
int ret[N][2], ans[N];
struct ques { int typ, x, y, z, val; };
vector<ques> all[MAX / 10];
ques arr[N * 10];
int pr, check[MAX], prs[MAX / 10], mp[MAX];
void dfs(int u)
{
dfn[u] = ++tt;
for (int i = st[u]; i; i = nx[i]) if (!dfn[to[i]]) dep[to[i]] = dep[u] + 1, dfs(to[i]);
out[u] = tt;
}
void init()
{
for (int i = 2; i <= MAX - 7; i++)
{
if (!check[i]