概述
题目链接:
http://www.spoj.com/problems/DIVCNT2/
根据rzz的课件 可以分三段做
度教搞出来一种分一次做的方法 看起来很神的样子
#include<cstdio>
#include<iostream>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<map>
using namespace std;
#define ll long long
char c;
inline void read(ll&a)
{a=0;do c=getchar();while(c<'0'||c>'9');while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();}
ll n;
const
ll MAXN=(int)1e8+1;
map<ll,ll >Mu,W,O;
int mu[MAXN],tot,prime[5761490],w[MAXN];
int cnt;
int D[2049];
inline ll m(ll x)
{
return mu[x]==mu[x-1]?0:(D[w[x]-w[x-1]]&1?-1:1);
}
ll SolveMu(ll n)
{
if(n<MAXN)return mu[n];
if(Mu[n])return Mu[n];
ll res=0;
for(ll i=1;i*1ll*i<=n;i++)
(res+=m(i)*(n/(i*i)));
return Mu[n]=res;
}
ll SolveW(ll n)
{
if(n<MAXN)return w[n];
if(W[n])return W[n];
ll res=0;
ll i=1,j;
while(i<=n)
{
j=n/(n/i);
(res+=(SolveMu(j)-SolveMu(i-1))*1ll*((n/i)));
i=j+1;
}
return W[n]=res;
}
ll SolveO(ll n)
{
if(O[n])return O[n];
ll res=0;
ll i=1,j;
while(i<=n)
{
j=n/(n/i);
(res+=(SolveW(j)-SolveW(i-1))*1ll*((n/i)));
i=j+1;
}
return O[n]=res;
}
void out(ll x)
{
if(x<0)putchar('-'),x=-x;
if(x>9)out(x/10);
putchar('0'+x%10);
}
ll Up;
vector<ll>Q;
int main()
{
Up=-1;
ll T;
mu[1]=w[1]=1;
read(T);
while(T--)
{
ll n;
read(n);
Q.push_back(n);
if(Up<n)Up=n;
//out(SolveO(n));
//puts("");
}
Up=min(Up+1,MAXN);
for(int i=2;i<Up;i++)
{
if(!w[i])prime[++tot]=i,mu[i]=-1,w[i]=2;
for(int j=1,k;j<=tot&&(k=prime[j]*i)<Up;j++)
{
if(i%prime[j]==0)
{mu[k]=0;w[k]=w[i];break;}
mu[k]=-mu[i];w[k]=w[i]*2;
}
mu[i]=mu[i-1]+mu[i]*mu[i];
w[i]+=w[i-1];
}
int j=1;
for(int i=0;i<=11;j*=2,i++)D[j]=i;
for(int i=0;i<Q.size();i++)
out(SolveO(Q[i])),puts("");
return 0;
}
最后
以上就是寂寞黑裤为你收集整理的SPOJ DIVCNT2的全部内容,希望文章能够帮你解决SPOJ DIVCNT2所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复