P4139 上帝与集合的正确用法

题目描述

根据一些书上的记载,上帝的一次失败的创世经历是这样的:

第一天, 上帝创造了一个世界的基本元素,称做“元”。

第二天, 上帝创造了一个新的元素,称作“α”。“α”被定义为“元”构成的集合。容易发现,一共有两种不同的“α”。

第三天, 上帝又创造了一个新的元素,称作“β”。“β”被定义为“α”构成的集合。容易发现,一共有四种不同的“β”。

第四天, 上帝创造了新的元素“γ”,“γ”被定义为“β”的集合。显然,一共会有16种不同的“γ”。

如果按照这样下去,上帝创造的第四种元素将会有65536种,第五种元素将会有2^65536种。这将会是一个天文数字。

然而,上帝并没有预料到元素种类数的增长是如此的迅速。他想要让世界的元素丰富起来,因此,日复一日,年复一年,他重复地创造着新的元素……

然而不久,当上帝创造出最后一种元素“θ”时,他发现这世界的元素实在是太多了,以致于世界的容量不足,无法承受。因此在这一天,上帝毁灭了世界。

至今,上帝仍记得那次失败的创世经历,现在他想问问你,他最后一次创造的元素“θ”一共有多少种?

上帝觉得这个数字可能过于巨大而无法表示出来,因此你只需要回答这个数对p取模后的值即可。

你可以认为上帝从“α”到“θ”一共创造了 10^9109 次元素,或 10^{18}1018 次,或者干脆∞次。

一句话题意:

% mod

输入输出格式

输入格式:

第一行一个整数 TT ,表示数据个数。

接下来 TT 行,每行一个正整数 pp ,代表你需要取模的值

输出格式:

TT 行,每行一个正整数,为答案对 pp 取模后的值

输入输出样例

输入样例#1:  复制
3
2
3
6
输出样例#1:  复制
0
1
4

说明

对于100%的数据,T1000,p10^7

题解:公式: 当 (b >= phi[p]) , a^b (mod p) 同余 a^(b%phi[p] + phi[p]) (mod p) , 当b < phi[p], ;

定义f(p) 为2的无限次方%p的指数,就可以递归下去了,注意递归中模数在变;

#include<bits/stdc++.h>
using namespace std;
 
const int M = 10005;
int n, q;
double yy[M*2];
struct Event{
    double x, y1, y2; int d;
};
vector <Event> e;
struct Node {
    double sum;
    int cnt;
    Node *ls , *rs;
     
    void up(int l, int r){
        if(cnt) sum = yy[r] - yy[l-1];
        else if(l != r)
            sum = ls->sum + rs->sum;
        else sum = 0;
    }
}pool[M << 4], *root, *tail = pool;
Node *build(int l = 1, int r = q){
    Node * nd = ++tail;
    if(l == r)nd->sum = 0, nd->cnt = 0;
    else {
        int mid = (l + r) >> 1;
        nd->ls = build(l, mid);
        nd->rs = build(mid + 1, r);
        nd->up(l ,r);
    }
}
#define Ls l, mid, nd -> ls
#define Rs mid+1, r, nd -> rs
void modify(int L, int R, int d, int l = 1, int r = q, Node * nd = root){
    if(L <= l && R >= r)nd->cnt += d, nd->up(l , r);
    else {
         int mid = (l + r) >> 1;
        if(L <= mid)modify(L, R, d, Ls);
        if(R > mid)modify(L, R, d, Rs);
        nd -> up(l, r);
    }
}
bool cmp(Event a, Event b){
    return a.x < b.x;
}
int main(){
    int k = 0;
    while(scanf("%d", &n) == 1){
        if(!n)break;
        k++; int cnt = 0;
        double ans = 0;
        e.clear();
        memset(yy, 0, sizeof(yy));
        for(int i = 1; i <= n; i++){
            double x1, x2, y1, y2;
            scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
            e.push_back((Event){x1, y1, y2, 1});
            e.push_back((Event){x2, y1, y2, -1});
            yy[++cnt] = y1; yy[++cnt] = y2;
        }
        sort(yy+1, yy+1+cnt);
        sort(e.begin(), e.end(), cmp);
        q = unique(yy+1, yy+1+cnt) - yy - 1;
        root = build();
        for(int i = 0; i < 2*n; i++){
            double dx = i == 0 ? 0 : e[i].x - e[i - 1].x;
            ans += root->sum * dx;
            int p1 = find(yy+1, yy+1+q, e[i].y1) - yy;
            int p2 = find(yy+1, yy+1+q, e[i].y2) - yy;
            modify(p1+1, p2, e[i].d);
            //cout<<ans<<endl;
        }
         
        printf("Test case #%d\nTotal explored area: %.2lf\n\n", k, ans);
    }   
}
View Code

猜你喜欢

转载自www.cnblogs.com/EdSheeran/p/9332428.html