【补题】Codeforces edu#50 ABCDE

版权声明:欢迎转载评论 https://blog.csdn.net/m0_37809890/article/details/82597174

总结

  1. 学习了accumulate的一些知识,如返回值类型,自定义求和函数。
  2. 双指针的一种写法:先for再while
  3. 写计算几何题一定要冷静的推公式,尽量用便于debug的写法去写。
  4. 数位dp的有关内容见之后的学习笔记。

1036A. Function Height

k除以n,取上整,(k+n-1)/n

1036B. Diagonal Walking v.2 结论

1e4个询问,每次给出第一象限的一个整点,问k步从原点走到(n,m),最多可以走几次对角。

如果k<max(n,m),走不到,输出-1。否则先斜走到和目标点同一直线处,再分类讨论。
记k为剩余步数,d为直线距离。
当k为偶数,d为偶数时,答案加k.
当k为奇数,d为偶数时,答案加k-2(注意可能出现无解情况).
当k为偶数,d为奇数时,答案加k-1.
当k为奇数,d为奇数时,答案加k-1.

1036C. Classy Numbers 数位dp

定义好看数字为含有不超过3个非0数字位的数字,1e4个询问,每次问两个数(1e18)之间好看数字的个数。

请看数位dp学习笔记

1036D. Vasya and Arrays 双指针

给出两个数组,每次操作可以选择数组中的连续一段,将它们替换为它们的和。问这两个数组能否操作成一样的,如果能,最终的数组最长可以有多长。

如果两个数组之和相同,则可以,否则不行。
从头开始双指针扫描,每有一段相同就截取下来并且给答案加一。

我的双指针写法有问题,最开始扫不到最后一个地方。
后来换了一种写法,对 i 进行外层for循环,对 j 进行内层while循环,每次第二个数组当前和比第一个数组大时就更新答案。

注意accumulate返回值的类型是第三个参数的类型,而不是容器类型。
accumulate可以添加第四个参数lambda表示行为,lambda函数的第一个参数类型应与accumulate的第三个参数相同,第二个参数类型应与元素类型相同。

ll A[M],B[M];
int main(void)
{
    #ifdef _LITTLEFALL_
    freopen("in.txt","r",stdin);
    #endif

    int n = read();
    for(int i=0;i<n;++i) A[i] = read();;
    int m = read();
    for(int i=0;i<m;i++) B[i] = read();
    if(accumulate(A,A+n,0ll) != accumulate(B,B+m,0ll))
        return !printf("-1\n");
    int ans = 0;
    ll sumA=0,sumB=0;
    for(int i=0,j=0;i<n;i++)
    {
        sumA += A[i];
        while(sumB < sumA)
            sumB += B[j++];
        if(sumA == sumB)
            ans++;
    }
    printf("%d\n",ans );

    return 0;
}

1036E. Covered Points 计算几何

给出n(1000)个各不同线的线段,线段的端点都在格点上,求这些线段一共覆盖了多少格点。

计算每个线段覆盖了多少个格点,再减去所有在格点上的交点就是答案。
每个线段覆盖的格点数目是 g c d ( Δ x , Δ y ) 。为了避免交点重复,用每一条线段与之前的线段求交,把交点放在set里,求完一轮后set的大小就是添加这条线段新产生的交点数。

为了便于判别交点是否在线段上,我让x1<x2,y1<y2,这样产生的结果是错误的,因为可能改变了斜率,应当只换一个,同步另一个。

struct Line
{
    ll x1,y1,x2,y2;
}line[M];
set<pair<ll,ll>> st;
void intersection(int l1, int l2)
{
    ll x1 = line[l1].x1, x2 = line[l1].x2, x3 = line[l2].x1, x4 = line[l2].x2;
    ll y1 = line[l1].y1, y2 = line[l1].y2, y3 = line[l2].y1, y4 = line[l2].y2;

    ll t1 = (y3-y1)*(x1-x2)*(x3-x4) + x1*(y1-y2)*(x3-x4) - x3*(y3-y4)*(x1-x2);
    ll t2 = (x3-x1)*(y1-y2)*(y3-y4) + y1*(x1-x2)*(y3-y4) - y3*(x3-x4)*(y1-y2);
    ll t3 = (y1-y2)*(x3-x4) - (y3-y4)*(x1-x2);
    if(t3==0 || t1%t3 || t2%t3) return;

    ll x = t1/t3;
    ll y = -t2/t3;

    if(y1>y2) swap(y1,y2);
    if(y3>y4) swap(y3,y4);
    if(y>=y1 && y<=y2 && y>=y3 && y<=y4)
        st.emplace(x,y);
}
int main(void)
{
    #ifdef _LITTLEFALL_
    freopen("in.txt","r",stdin);
    #endif

    int n = read();
    ll ans = 0;
    for(int i=0;i<n;i++)
    {
        Line &l = line[i];
        l.x1 = read(); l.y1 = read();
        l.x2 = read(); l.y2 = read();
        if(l.x1>l.x2) swap(l.x1, l.x2), swap(l.y1, l.y2);
        ans += __gcd(l.x2-l.x1, abs(l.y2-l.y1)) + 1;
    }
    for(int i=0;i<n;i++)
    {
        st.clear();
        for(int j=0;j<i;j++)
            intersection(i,j);
        ans -= st.size();
    }

    printf("%I64d\n",ans );

    return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_37809890/article/details/82597174