【刷題】BZOJ 2190 [SDOI2008]儀仗隊
阿新 • • 發佈:2018-03-30
AD 100% puts IT gist logs www sample blog
然後對於這個矩陣
\(ans'=\sum_{i=1}^n\sum_{j=1}^n[gcd(i,j)=1]\)
\(\ \ \ \ \ \ \ \ =\sum_{i=1}^n\mu(i)(\lfloor \frac{n}{i}\rfloor )^2\)
然後加上原來的最後一行和第一列的貢獻,就是加2
答案就是\(ans=ans'+2\)
當然,這種做法要特判一下,因為我們剔掉了一行一列,那麽當 \(n=1\) 的時候,答案特判,為0
Description
作為體育委員,C君負責這次運動會儀仗隊的訓練。儀仗隊是由學生組成的N * N的方陣,為了保證隊伍在行進中整齊劃一,C君會跟在儀仗隊的左後方,根據其視線所及的學生人數來判斷隊伍是否整齊(如下圖)。
現在,C君希望你告訴他隊伍整齊時能看到的學生人數。
Input
共一個數N。
Output
共一個數,即C君應看到的學生人數。
Sample Input
4
Sample Output
9
HINT
【數據規模和約定】 對於 100% 的數據,1 ≤ N ≤ 40000
Solution
以前看這題,無從下手
現在看這題,毫無意義
由於這個什麽人在隊列的左下角,所以我們先把第一列和最後一行去掉,剩下的變成一個矩陣
\(ans'=\sum_{i=1}^n\sum_{j=1}^n[gcd(i,j)=1]\)
\(\ \ \ \ \ \ \ \ =\sum_{i=1}^n\mu(i)(\lfloor \frac{n}{i}\rfloor )^2\)
然後加上原來的最後一行和第一列的貢獻,就是加2
答案就是\(ans=ans'+2\)
當然,這種做法要特判一下,因為我們剔掉了一行一列,那麽當 \(n=1\) 的時候,答案特判,為0
#include<bits/stdc++.h>
#define ll long long
#define db double
#define ld long double
const int MAXN=40000+10;
int n,vis[MAXN],prime[MAXN],cnt,s[MAXN],mu[MAXN];
ll res=0;
template<typename T> inline void read(T &x)
{
T data=0,w=1;
char ch=0;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while (ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
x=data*w;
}
template<typename T> inline void write(T x,char c='\0')
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
if(c!='\0')putchar(c);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline void init()
{
memset(vis,1,sizeof(vis));
vis[0]=vis[1]=1;
mu[1]=1;
for(register int i=2;i<MAXN;++i)
{
if(vis[i])
{
prime[++cnt]=i;
mu[i]=-1;
}
for(register int j=1;j<=cnt&&i*prime[j]<MAXN;++j)
{
vis[i*prime[j]]=0;
if(i%prime[j])mu[i*prime[j]]=-mu[i];
else break;
}
}
for(register int i=1;i<MAXN;++i)s[i]=s[i-1]+mu[i];
}
int main()
{
init();
read(n);
if(n<=1)
{
puts("0");
return 0;
}
n--;
for(register int i=1;;)
{
if(i>n)break;
int j=n/(n/i);
res+=1ll*(n/i)*(n/i)*(s[j]-s[i-1]);
i=j+1;
}
write(res+2,'\n');
return 0;
}
【刷題】BZOJ 2190 [SDOI2008]儀仗隊