题解 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;
}