• 【洛谷P2231】跳蚤


    题目

    题目链接:https://www.luogu.com.cn/problem/P2231
    题面没有 LaTeX 太丑了,所以直接上题意简述吧。
    给出 (n,m),求有多少个长度为 (n) 的序列,满足序列中所有数均为 ([1,m]) 的整数且数列的 (gcd)(m) 互质。

    思路

    (m) 视作数列第 (n+1) 项,问题转化为有多少个长度为 (n+1) 且最后一项为 (m) 的数列的 (gcd)(1)
    (f[i]) 表示整个数列的 (gcd=i) 的方案数。因为整个数列与 (m)(gcd) 一定是 (m) 的因子,所以 (f[i]) 最多只有 (2sqrt{m}) 个位置有元素,所以直接拿一个 unorder_map 存即可。
    可以发现 (f[i]=gcd)(i) 的倍数的方案数 (-sum_{i|j,jleq m} f[j])。而前面的那一部分显然等于 (lfloor frac{m}{i} floor^n),所以我们可以从大到小枚举 (m) 的因子,计算出前面部分,然后用这个因子去贡献它的因子。最终答案即为 (f[1])
    时间复杂度 (O(m))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    int n,m;
    unordered_map<int,ll> f;
    
    ll fpow(ll x,ll k)
    {
    	ll ans=1;
    	for (;k;k>>=1,x=x*x)
    		if (k&1) ans=ans*x;
    	return ans;
    }
    
    void calc(int x)
    {
    	f[x]+=fpow(m/x,n);
    	for (int i=1;i*i<=x;i++)
    		if (x%i==0)
    		{
    			if (i!=x) f[i]-=f[x];
    			if (i*i!=x && i!=1) f[x/i]-=f[x];
    		}
    }
    
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for (int i=1;i*i<=m;i++)
    		if (m%i==0) calc(m/i);
    	for (int i=sqrt(m-1);i>=1;i--)
    		if (m%i==0) calc(i);
    	printf("%lld",f[1]);
    	return 0;
    }
    
  • 相关阅读:
    Spring-boot 项目中使用 jackson 遇到的一个问题
    Spring Cloud 简介
    VSCode配置JAVA开发环境
    Smtp错误码
    Git遇到的问题
    对于static静态
    面向对象
    类与对象的概念
    java执行过程
    nacos安装部署
  • 原文地址:https://www.cnblogs.com/stoorz/p/14032850.html
Copyright © 2020-2023  润新知