[蓝桥杯 2023 省 A] 翻转硬币

  • 10000000的数组开多了空间也是有可能不够的……
#include <bits/stdc++.h>
#define int long long
using namespace std;
signed v[10000005],prime[10000005],m;
signed miu[10000005],smiu[10000005];
void mobius(int n)
{
    miu[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(v[i]==0)
        {
            v[i]=i;
            prime[++m]=i;
            miu[i]=-1;
        }
        for(int j=1;j<=m;j++)
        {
            if(i*prime[j]>n||prime[j]>v[i])
            {
                break;
            }
            v[i*prime[j]]=prime[j];
            int x=i,y=prime[j],cnt=1;
            while(x%prime[j]==0)
            {
                x/=prime[j];
                y*=prime[j];
                cnt++;
            }
            if(x==1)
            {
                miu[x*y]=0;
            }
            else
            {
                miu[x*y]=miu[x]*miu[y];
            }
        }
    }
    for(int i=1;i<=n;i++)
    {
        smiu[i]=smiu[i-1]+miu[i];
    }
}
unordered_map<int,int>qmiu;
int Smiu(int n)
{
	if(n<=10000000)
	{
		return smiu[n];
	}
	else if(qmiu.find(n)!=qmiu.end())
	{
		return qmiu[n];
	}
	else
	{
		int ans=1;
		for(int d=2;d<=n;d++)
		{
			int p=n/(n/d);
			ans=ans-(p-d+1)*Smiu(n/d);
			d=p;
		}
		return qmiu[n]=ans;
	}
}
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	mobius(10000000);
	int n;
	cin>>n;
	int ans=0;
	for(int d=1;d*d<=n;d++)
	{
		int p=sqrt(n/(n/(d*d)));
		ans+=((Smiu(p)-Smiu(d-1))*(n/(d*d)));
		d=p;
	}
	cout<<ans<<"\n";
	return 0;
}
posted @ 2025-04-02 19:45  D06  阅读(41)  评论(0)    收藏  举报
//雪花飘落效果