zoukankan      html  css  js  c++  java
  • 20200713 T1序列问题

    题目描述

    ( ext{Tom}) 的梦想是成为世界冠军。因此他每天都在认真做题。

    某天他在学数学的时候又造出了一个新题,并准备以此为难你一下。

    给定长度为 (n) 的序列,正整数 (k),可以定义两个函数:

    (F(i)=i^{a[i]} mod k)

    (G(i)=a[i]^{i} mod k)

    现在要求计算((l,r))数对的数量,其中 (1 leq l < r leq n),且 (f(l)>g(r))

    输入格式

    (1)(2) 个整数 (n)(k)

    (2) 行读入 (n) 个整数 (a_1,a_2 dots a_n)

    输出格式

    一行输出答案。

    样例

    input1

    5 10000
    3 1 5 4 2
    

    output1

    2
    

    数据规模和限制

    对于全部测试数据,满足 (N leq 10^5)(k leq 10^9)(a_i leq 10^9)

    各个测试点的数据规模及特殊性质如下表。

    测试点 N (a_i)
    (1 sim 3) (leq 100) (leq 100)
    (4 sim 6) (leq 3000) (leq 10 ^ 5)
    (7 sim 10) (leq 10 ^ 5) (leq 10 ^ 9)

    题解

    先计算出 (f[i])(g[i]),然后离散化一下,放到权值线段树上找逆序对个数。
    别的找逆序对的方法也行

    Code

    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #define MAXN 300001
    #define lson now << 1
    #define rson now << 1 | 1
    
    long long ans;
    int n, mod, a[MAXN], f[MAXN], g[MAXN];
    struct lsh {
    	int w, num;
    	friend bool operator < (lsh x, lsh y) {
    		return x.w < y.w;
    	}
    }b[MAXN];
    struct Node {
    	int l, r, w;
    }tree[MAXN << 1];
    
    void build(int l, int r, int now) {
    	tree[now].l = l, tree[now].r = r;
    	if (tree[now].l == tree[now].r) {
    		tree[now].w = 0;
    		return;
    	}
    	int mid = (tree[now].l + tree[now].r) >> 1;
    	build(l, mid, lson), build(mid + 1, r, rson);
    	tree[now].w = tree[lson].w + tree[rson].w;
    }
    
    void add(int x, int now) {
    	if (tree[now].l == tree[now].r) {
    		++tree[now].w;
    		return;
    	}
    	int mid = (tree[now].l + tree[now].r) >> 1;
    	if (x <= mid) add(x, lson);
    	else add(x, rson);
    	tree[now].w = tree[lson].w + tree[rson].w;
    }
    
    int query(int x, int y, int now) {
    	if (tree[now].l >= x && tree[now].r <= y) return tree[now].w;
    	int mid = (tree[now].l + tree[now].r) >> 1, ans = 0;
    	if (x <= mid) ans += query(x, y, lson);
    	if (y > mid) ans += query(x, y, rson);
    	return ans;
    }
    
    int qpow(int a, int b) {
    	int ans = 1, base = a;
    	while(b) {
    		if (b & 1) ans = 1ll * ans * base % mod;
    		base = 1ll * base * base % mod;
    		b >>= 1;
    	}
    	return ans % mod;
    }
    
    int main() {
    	scanf("%d %d", &n, &mod);
    	for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
    	for (int i = 1; i <= n; ++i) {
    		f[i] = qpow(i, a[i]);
    		b[i].w = f[i];
    		b[i].num = i; 
    		g[i] = qpow(a[i], i);
    		b[i + n].w = g[i];
    		b[i + n].num = -i;
    	}
    	std::sort(b + 1, b + 2 * n + 1);
    	int now = 0;
    	for (int i = 1; i <= 2 * n; ++i) {
    		if (b[i].w != b[i - 1].w) ++now;
    		if (b[i].num > 0) f[b[i].num] = now;
    		else g[-b[i].num] = now;
    	}
    	build(1, 2 * n, 1);
    	for (int i = n; i > 1; --i) {
    		add(g[i], 1);
    		if (f[i - 1] == 1) continue;
    		ans += query(1, f[i - 1] - 1, 1);
    	}
    	printf("%lld
    ", ans);
    	return 0;
    }
    

    反思

    考场上以为自己写了个 60pts 的算法实际上是 30pts 的算法。写完之后一定要检查啊qwq。

  • 相关阅读:
    简单的测试用例计划放法
    黑盒测试用例设计方法-等价类划分
    Redis净化板
    爬虫部署与Django
    怎样实现前端的优化
    关于Apache简介笔记
    yield生成器的经典案例
    石头剪刀布
    函数内是否可以修改传递进来的列表
    不定长参数的传递
  • 原文地址:https://www.cnblogs.com/poi-bolg-poi/p/13295486.html
Copyright © 2011-2022 走看看