HDU6053(72/600)

本文介绍了一道使用莫比乌斯反演解决的算法题,题目要求计算满足特定条件的不同数组数量。通过实现代码详细展示了如何运用莫比乌斯函数及反演技巧来求解此类问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Problem Description
You are given an array A , and Zhu wants to know there are how many different array B satisfy the following conditions?

  • 1≤Bi≤Ai
  • For each pair( l , r ) (1≤l≤r≤n) , gcd(bl,bl+1…br)≥2

Input
The first line is an integer T(1≤T≤10) describe the number of test cases.

Each test case begins with an integer number n describe the size of array A.

Then a line contains n numbers describe each element of A

You can assume that 1≤n,Ai≤105

Output
For the kth test case , first output “Case #k: ” , then output an integer as answer in a single line . because the answer may be large , so you are only need to output answer mod 109+7

Sample Input
1
4
4 4 4 4

Sample Output
Case #1: 17

Source
2017 Multi-University Training Contest - Team 2

Recommend
liuyiding | We have carefully selected several similar problems for you: 6055 6054 6053 6052 6051

莫比乌斯反演的第一次用….
其实就是说莫比乌斯反演那个公式可以反过来用….
用大的算小的…

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=200105;
int normal[maxn];
int mu[maxn];
int prime[maxn];
int pcnt,u=0;
void Init()
{
    memset(normal,0,sizeof(normal));
    mu[1] = 1;
    pcnt = 0;
    for(int i=2; i<maxn; i++)
    {
        if(!normal[i])
        {
            prime[pcnt++] = i;
            mu[i] = -1;
        }
        for(int j=0; j<pcnt&&i*prime[j]<maxn; j++)
        {
            normal[i*prime[j]] = 1;
            if(i%prime[j]) mu[i*prime[j]] = -mu[i];
            else
            {
                mu[i*prime[j]] = 0;
                break;
            }
        }
    }
}
int tu[maxn],sum[maxn],n,q;
ll mo=1e9+7;
ll ksm(ll ds,ll zs)
{
    ll fs=1;
    while(zs)
    {
        if(zs&1)fs*=ds;

        fs%=mo;
        ds*=ds;
        ds+=mo;
        ds%=mo;
        zs>>=1; //cout<<zs<<endl;
    }
    return (fs+mo)%mo;
}
ll f[maxn],F[maxn];
int main()
{
    Init();
//  cout<<ksm(2,2)<<endl;
//  return 0;
    int T;
    cin>>T;
    while(T--)
    {
        cin>>n;
        memset(f,0,sizeof(f));
        memset(F,0,sizeof(F));
        memset(tu,0,sizeof(tu));
        memset(sum,0,sizeof(sum));
        int shang=0,xia=1e9;
        for(int a=1;a<=n;a++)
        {
            scanf("%d",&q);
            tu[q]++;
            shang=max(shang,q);
            xia=min(xia,q);
        }
        for(int a=1;a<=200010;a++)
        {
            sum[a]=sum[a-1]+tu[a];
        }
        for(int a=2;a<=xia;a++)
        {
            F[a]=1;
            for(int b=a;b<=shang;b+=a)
            {
                int qj=b/a;
        //      int y=min(,shang);
            //  cout<<"ccccc";
    //      cout<<sum[y]-sum[b-1]<<endl<<qj<<endl;
                F[a]=(F[a]*ksm(qj,sum[b+a-1]-sum[b-1])%mo+mo)%mo;
            }//cout<<"asd";
        }
    //  return 0;
        for(int a=2;a<=xia;a++)
        {
            for(int b=1;;b++)
            {
                if(b*a>xia)break;
                f[a]=(f[a]+mu[b]*F[a*b]+mo)%mo;
            }
        }

        ll dan=0;
        for(int a=2;a<=xia;a++)
        {
            dan=(dan+f[a]+mo)%mo;
        }
        printf("Case #%d: %lld\n",++u,dan%mo);
    }
}
资源下载链接为: https://pan.quark.cn/s/1bfadf00ae14 在 Linux 系统中,查找域名或主机名对应的 IP 地址是网络管理中的一项基础且关键任务,对于排查网络故障、调试网络问题以及监控网络服务是否正常运行等场景都非常重要。本文将介绍五种在 Linux 终端查询域名 IP 地址的方法。 首先,dig 命令(全称 Domain Information Groper)是一个功能强大的 DNS 查询工具,能够向 DNS 服务器发送查询请求并获取详细的响应信息。如果需要查询单个域名的 IP 地址,可以使用命令 dig 2daygeek.com +short 。此外,还可以通过编写 bash 脚本,将包含域名的文本文件中的域名逐个读取,然后利用 dig 命令进行查询,从而实现批量查询域名 IP 地址的功能。 其次,host 命令是一个简单易用的 DNS 查询工具,主要用于将域名解析为 IP 地址。要获取某个域名的 IP 地址,直接使用 host 2daygeek.com 即可。如果只想显示 IP 地址部分,可以通过管道结合 grep 和 sed 命令来实现,例如:host 2daygeek.com | grep "has address" | sed s/has address/-/g 。 再者,nslookup 命令也是一种常用的 DNS 查询工具,它支持交互式查询 DNS 信息。通过 nslookup 2daygeek.com 可以查询域名的 IP 地址。若要以非交互式的方式只显示 IP 地址,可以使用命令 nslookup 2daygeek.com | awk /^Address:/ {print $2} 。 另外,fping 命令与传统的 ping 命令不同,它不会直接进行 DNS 查询,而是通过发送 ICMP Echo Request(pi
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值