Codeforces 755D-PolandBall and Polygon

PolandBall and Polygon
time limit per test
4 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

PolandBall has such a convex polygon with n veritces that no three of its diagonals intersect at the same point. PolandBall decided to improve it and draw some red segments.

He chose a number k such that gcd(n, k) = 1. Vertices of the polygon are numbered from 1 to n in a clockwise way. PolandBall repeats the following process n times, starting from the vertex 1:

Assume you've ended last operation in vertex x (consider x = 1 if it is the first operation). Draw a new segment from vertex x to k-th next vertex in clockwise direction. This is a vertexx + k or x + k - n depending on which of these is a valid index of polygon's vertex.

Your task is to calculate number of polygon's sections after each drawing. A section is a clear area inside the polygon bounded with drawn diagonals or the polygon's sides.

Input

There are only two numbers in the input: n and k (5 ≤ n ≤ 1062 ≤ k ≤ n - 2gcd(n, k) = 1).

Output

You should print n values separated by spaces. The i-th value should represent number of polygon's sections after drawing first i lines.

Examples
input
5 2
output
2 3 5 8 11 
input
10 3
output
2 3 4 6 9 12 16 21 26 31 
Note

The greatest common divisor (gcd) of two integers a and b is the largest positive integer that divides both a and b without a remainder.

For the first sample testcase, you should output "2 3 5 8 11". Pictures below correspond to situations after drawing lines.

题目大意:一个n边形,从1号点开始,每次走到(x+k-1)%n+1位置,问每次留下来的路径把这个多边形划分成了几个部分。
解题思路:
新加入一条直线后的区域块数 = 原有的区域块数 + 与该直线相交直线的条数 +1,在查询与新加入直线相交直线的条数时可以用树状数组


#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <set>
#include <map>

using namespace std;

#define LL long long

const int maxn = 1e6+10;
int a[maxn],n,k;

int lowbit(int x)
{
    return x&-x;
}

int getsum(int x)
{
    int sum=0;
    while(x>0)
    {
        sum+=a[x];
        x-=lowbit(x);
    }
    return sum;
}

void add(int x)
{
    while(x<=n)
    {
        a[x]+=1;
        x+=lowbit(x);
    }
}

int main()
{
    while(~scanf("%d %d",&n,&k))
    {
        LL ans=1;
        int s=1,e;
        memset(a,0,sizeof(a));
        if(k>(n/2)) k=n-k;
        for(int i=0; i<n; ++i)
        {
            e=s+k;
            if(e>n) e-=n;
            if(s<e) ans+=getsum(e-1)-getsum(s)+1;
            else ans+=getsum(n)-getsum(s)+getsum(e-1)+1;
            if(i!=n-1) printf("%lld ",ans);
            else printf("%lld\n",ans);
            add(s);
            add(e);
            s=e;
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值