BZOJ3994: [SDOI2015]约数个数和

很难想到。。
http://blog.codebursts.com/bzoj3994/

然后我是暴力求f的。。。
总体时间还是一样的

#include<cstdio>
#include<iostream>
using namespace std;
#define ll long long
const
   int maxn=50001;
ll mu[maxn],pre[maxn];
bool check[maxn];
int prime[maxn],tot;
int f[maxn];

char c;
inline void read(int &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();
}


int main()
{
   int n,last,i,j,k,m;
   for(n=1;n<maxn;n++)
   {
     i=1;
      while(i<=n)
      {
         last=n/(n/i)+1;
         last=min(n+1,last);
         f[n]+=(last-i)*(n/i);      
         i=last;
      }
   }
   mu[1]=1;pre[1]=1;
    for(i=2;i<maxn;i++)
    {
        if(!check[i])
           prime[++tot]=i,mu[i]=-1;
        pre[i]=pre[i-1]+mu[i];
        for(j=1;j<=tot;j++)
         {
            k=prime[j]*i;
            if(k>maxn)break;
            if(i%prime[j]==0){mu[k]=0;check[k]=true;break;}
            check[k]=true,mu[k]=-mu[i];
         }
    }
    int T;
    ll ans;
    read(T);
    while(T--)
    {
        read(n),read(m);
        if(m<n)swap(n,m);
        i=1;
        ans=0;
        while(i<=n)
        {
            last=min(n/(n/i)+1,m/(m/i)+1);
            last=min(n+1,last);
            ans+=
            (pre[last-1]-pre[i-1])*f[n/i]*f[m/i]; i=last; } printf("%lld\n",ans); } return 0; }

你可能感兴趣的:(BZOJ3994: [SDOI2015]约数个数和)