hdu 1542 求矩形并的面积

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstdlib>
using namespace std;
#define M 1010
typedef int I;
typedef double D;
typedef struct
{
    D x;
    D y_down;
    D y_up;
    I cover;
} node;//定义线段,每一个都存一个x并且cover标记是左边的还是右边的,y_down和y_up表示这一线段对应y的坐标
node L[3*M];
typedef struct tr
{
    I l,r;
    I cover;
    D len;
} tree;//定义树的结构,cover表示这条边有没有被覆盖过,len表示这一段区间的y轴的长度
tree t[3*M];
D yy[M];//对y坐标进行离散用
I cmp(node a,node b)
{
    return a.x < b.x;
}
void build(I id,I l,I r)
{
    t[id].cover=0;
    t[id].l=l;
    t[id].len=0;
    t[id].r=r;
    if(l+1==r) return ;
    I mid=(l+r)>>1;
    build(id<<1,l,mid);
    build(id<<1|1,mid,r);
}
void fun(I id)
{
    if(t[id].cover)//如果被覆盖则此段的长度len为对应y坐标之差
        t[id].len=yy[t[id].r]-yy[t[id].l];
    else if(t[id].l+1==t[id].r)//若为叶子节点,长度len为0
        t[id].len=0;
    else//若没有被覆盖过,并且不是叶子节点,则此段的长度为下面分支对应长度之和
        t[id].len=t[id<<1].len+t[id<<1|1].len;
}
void update(I id,I l,I r,I v)
{
    if(t[id].l>=r || t[id].r<=l)//如果没有在这个距离内,直接返回,不用再向下搜了
        return ;
    if(t[id].l<=l && t[id].r<=r)//若此段包含着,则说明,被覆盖
    {
        t[id].cover+=v;
        fun(id);//查找此段的长度len
        return ;
    }
    update(id<<1,l,r,v);//如果以上都不满足则继续向下搜
    update(id<<1|1,l,r,v);
    fun(id);//最后还要搜一下长度
}
I find(I l,I r,D x)//二分查找,对y坐标进行离散化
{
    while(l<=r)
    {
        I mid=(l+r)>>1;
        if(fabs(yy[mid]-x)<1e-10)
            return mid;
        else if(yy[mid]>x)
            r=mid-1;
        else
            l=mid+1;
    }
    return l;
}
I main()
{
    I n,i,ca;
    ca=1;
    while(scanf("%d",&n),n)
    {
        I m;
        m=0;
        for(i=0; i<n; i++)
        {
            D x1,x2,y1,y2;
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            yy[m]=y1;  //把坐标定点记录成线段,每条线段保存的信息有,线段的定点,还有在这个句型中的位置,左边还是右边
            L[m].cover=1;
            L[m].x=x1;
            L[m].y_down=y1;
            L[m].y_up=y2;
            m++;
            yy[m]=y2;
            L[m].cover=-1;
            L[m].x=x2;
            L[m].y_down=y1;
            L[m].y_up=y2;
            m++;
        }
        I len=1;
        sort(yy,yy+m);//对y进行升序排序
        for(i=1; i<m; i++)//去重
        {
            if(yy[i-1]!=yy[i])
                yy[len++]=yy[i];
        }
        len--;
        build(1,0,len);//建树,以离散后y坐标为区间建树
        sort(L,L+m,cmp);
        D ans=0;
        for(i=0; i<m-1; i++)
        {
            I a,b;
            a=find(0,len,L[i].y_down);
            b=find(0,len,L[i].y_up);
            update(1,a,b,L[i].cover);//更新对应区间
            ans+=t[1].len*(L[i+1].x-L[i].x);//累加求此段被分割的面积
        }
        //输出
        printf("Test case #%d\n",ca++);
        printf("Total explored area: %.2f\n",ans);
    }
    return 0;
}

好的,关于 HDU4992 所有原根的问题,我可以给出以下解答: 1. 首先,我们需要知道什么是原根。原根是指模 n 意义下,所有与 n 互质的数 a 的最小正整数 k 次幂对 n 取模的值覆盖了所有与 n 互质的数。简单来说,就是如果一个数 a 是模 n 意义下的原根,那么 a 的任何正整数次幂对 n 取模的值都不相同,且能覆盖所有与 n 互质的数。 2. 为了模 n 意义下的所有原根,我们需要先出与 n 互质的数的个数 phi(n)。phi(n) 可以使用欧拉函数出。 3. 然后,我们需要枚举模 n 意义下的所有数,判断它是否是原根。具体来说,对于每个 a,我们需要判断 a 的每个小于 phi(n) 的正整数次幂对 n 取模的值是否都不相同,且能覆盖所有与 n 互质的数。如果是,那么 a 就是模 n 意义下的原根。 4. 代码实现可以参考以下 Java 代码: ``` import java.util.*; public class Main { static int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); } static int phi(int n) { int res = n; for (int i = 2; i * i <= n; i++) { if (n % i == 0) { res = res / i * (i - 1); while (n % i == 0) { n /= i; } } } if (n > 1) { res = res / n * (n - 1); } return res; } static int pow(int a, int b, int mod) { int res = 1; while (b > 0) { if ((b & 1) != 0) { res = res * a % mod; } a = a * a % mod; b >>= 1; } return res; } static boolean check(int a, int n, int phi) { for (int i = 1, j = pow(a, i, n); i <= phi; i++, j = j * a % n) { if (j == 1) { return false; } } return true; } public static void main(String[] args) { Scanner scanner = new Scanner(System.in); while (scanner.hasNext()) { int n = scanner.nextInt(); int phi = phi(n); List<Integer> ans = new ArrayList<>(); for (int i = 1; i < n; i++) { if (gcd(i, n) == 1 && check(i, n, phi)) { ans.add(i); } } Collections.sort(ans); for (int x : ans) { System.out.print(x + " "); } System.out.println(); } } } ``` 其中,gcd 函数用于最大公约数,phi 函数用于欧拉函数,pow 函数用于快速幂模,check 函数用于判断一个数是否是原根。在主函数中,我们依次读入每个 n,出 phi(n),然后枚举模 n 意义下的所有数,判断它是否是原根,将所有原根存入一个 List 中,最后排序输出即可。 希望我的回答能够帮到你,如果你有任何问题,欢迎随时提出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值