题解 P2158 【[SDOI2008]仪仗队】

· · 题解

和其他题解不大一致。

先将图分成两个直角三角形

令f[i]表示在第i排所能看到的最大个数,

容易发现一个性质,即对于这个数能看到得点,那么其倍数就一定被不能看到这些点延长过来的点。

那么就用类似线性筛得算法处理一遍即可。

答案即为ans*2+1

#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i = x ;i <= y; ++ i)
#define repd(i,x,y) for(register int i = x ;i >= y; -- i)
using namespace std;
typedef long long ll;
template<typename T>inline bool chkmin(T&x,T y) { return x > y ? x = y,1 : 0; }
template<typename T>inline bool chkmax(T&x,T y) { return x < y ? x = y,1 : 0; }
template<typename T>inline void read(T&x)
{
    x = 0;char c;int sign = 1;
    do { c = getchar(); if(c == '-'); }while(!isdigit(c));
    do { x = x * 10 + c - '0'; c = getchar(); }while(isdigit(c));
    x *= sign;
}

const int N = 1e5 + 500; 
int n,ans,f[N];
bool vis[N];

inline void solve()
{
    memset(f,-1,sizeof f);
    f[1] = 1; ans += f[1];
    rep(i,2,n)
    {
        f[i] += i; ans += f[i];
        for(register int j = 2*i;j <= n;j += i)
            f[j] -= f[i];
    }

}

int main()
{
    read(n);n--;

    solve();

    cout << ans * 2 + 1;

    return 0;
}