看原题请戳下面
题目内容什么的就不赘述了,看图吧。
设index为当前点,则index+k为终点。
不难看出增量为这两点之间的所有点的线段数之和再加1.
数据范围比较大,暴力会超时,所以用树状数组来求解。不会树状数组的话可以戳这里。~树状数组详解~
另外,一个凸n边形,增量为k,和增量为(n-k)得到的结果相同,此处不再证明。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <vector>
#include <map>
#include <iomanip>
using namespace std;
long long v[1000010];
long long c[1000010];
long long C(int i)
{
long long temp = 0;
int index = i + 1 - (i&(-i));
while(index <= i)
{
temp+=v[index];
index++;
}
return temp;
}
long long SUM(int i)
{
long long s = 0;
while(i>0)
{
s+=c[i];
i -= (i&(-i));
}
return s;
}
void Update(int i,int add,int SIZE)
{
while(i<=SIZE)
{
c[i] += add;
i += (i&(-i));
}
}
int main()
{
int n,k;
while(cin>>n>>k)
{
memset(v,0,sizeof(v));
k=min(k,n-k);
for(int i=1; i<=n; i++)
{
if(i == 1||i == k+1)
v[i] = 1;
else
v[i] = 0;
c[i] = C(i);
}
cout<<"2";
int index = k+1;
long long tempsum = 2;
for(int i=2; i<=n; i++)
{
if(index+k>n)
{
tempsum += SUM(n) - SUM(index);
tempsum += SUM((index+k)-n-1);
tempsum++;
Update(index,1,n);
index = (index+k)-n;
Update(index,1,n);
}
else
{
tempsum += SUM(index+k-1) - SUM(index);
tempsum++;
Update(index,1,n);
index = (index+k);
Update(index,1,n);
}
cout<<" "<<tempsum;
}
cout<<endl;
}
}