HDU-4407-Sum(容斥原理)「建议收藏」

HDU-4407-Sum(容斥原理)

大家好,又见面了,我是全栈君。

Problem Description
XXX is puzzled with the question below: 

1, 2, 3, …, n (1<=n<=400000) are placed in a line. There are m (1<=m<=1000) operations of two kinds.

Operation 1: among the x-th number to the y-th number (inclusive), get the sum of the numbers which are co-prime with p( 1 <=p <= 400000).

Operation 2: change the x-th number to c( 1 <=c <= 400000).

For each operation, XXX will spend a lot of time to treat it. So he wants to ask you to help him.

 


Input
There are several test cases.

The first line in the input is an integer indicating the number of test cases.

For each case, the first line begins with two integers — the above mentioned n and m.

Each the following m lines contains an operation.

Operation 1 is in this format: “1 x y p”. 

Operation 2 is in this format: “2 x c”.
 


Output
For each operation 1, output a single integer in one line representing the result.

 


Sample Input
   
   
1 3 3 2 2 3 1 1 3 4 1 2 3 6

 


Sample Output
   
   
7 0

 


Source

#include <stdio.h>

int num,idx[1005],val[1005],prime[10],p[40000];

inline bool check(int x)
{
    int i;

    for(i=0;i<num;i++) if(x%prime[i]==0) return 0;

    return 1;
}

int main()
{
    int T,n,m,i,j,k,type,cnt,a,b,c,last,lxdcnt,lxdnum,l,r;
    long long ans;

    //把40W以内的素数预处理出来-----------------
    cnt=0;

    for(i=2;i<400000;i++)
    {
        for(j=2;j*j<=i;j++) if(i%j==0) break;

        if(j*j>i) p[cnt++]=i;
    }
    //------------------------------------------

    scanf("%d",&T);

    while(T--)
    {
        scanf("%d%d",&n,&m);

        cnt=0;

        for(i=1;i<=m;i++)
        {
            scanf("%d",&type);

            if(type==1)
            {
                scanf("%d%d%d",&a,&b,&c);

                ans=(long long)(a+b)*(b-a+1)/2;

                num=0;//质因数的个数

                //获取c的质因数-----------------
                last=0;

                while(c>1)
                {
                    if(c%p[last]==0)
                    {
                        prime[num++]=p[last];
                        c/=p[last];
                        while(c%p[last]==0) c/=p[last];
                    }

                    last++;
                }
                //-------------------------------

                //容斥原理-------------------------
                for(j=1;j<(1<<num);j++)
                {
                    lxdcnt=0;
                    lxdnum=1;

                    for(k=0;k<num;k++) if(j&(1<<k))
                    {
                        lxdcnt++;
                        lxdnum*=prime[k];
                    }


                    l=a/lxdnum*lxdnum;
                    if(l<a) l+=lxdnum;
                    r=b/lxdnum*lxdnum;
                    if(r<l) continue;

                    if(lxdcnt&1) ans-=(long long)(l+r)*((r-l)/lxdnum+1)/2;
                    else ans+=(long long)(l+r)*((r-l)/lxdnum+1)/2;
                }
                //-----------------------------------

                //对改动过的数字特殊推断-----------------------------------
                for(j=0;j<cnt;j++)
                {
                    if(idx[j]>=a && idx[j]<=b)
                    {
                        if(!check(idx[j]))
                        {
                            if(check(val[j])) ans+=val[j];
                        }
                        else
                        {
                            if(check(val[j])) ans=ans+val[j]-idx[j];
                            else ans-=idx[j];
                        }
                    }
                }
                //--------------------------------------------------------

                printf("%I64d\n",ans);
            }
            else
            {
                scanf("%d%d",&a,&b);

                for(j=0;j<cnt;j++) if(idx[j]==a)//注意,改动的点可能之前已被改动过
                {
                    val[j]=b;
                    break;
                }

                if(j==cnt)
                {
                    idx[cnt]=a;
                    val[cnt++]=b;
                }
            }
        }
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/115923.html原文链接:https://javaforall.net

(0)
上一篇 2022年1月28日 下午5:00
下一篇 2022年1月28日 下午7:00


相关推荐

  • win10打开wireshark显示没有找到接口的解决方法

    win10打开wireshark显示没有找到接口的解决方法好久没用 wireshark 抓包 今天打开 wireshark 软件显示没有找到接口 如下 后续开始百度 网上常见的主要是以下两种解决方法 1 wireshark 自带的 Npcap 不支持 win10 需要重新下载 Win10Pcap 下载地址为 http www win10pcap org download 安装时需要关闭 wireshark 然后重新打开 wireshark 即可 2 使用管理

    2026年3月20日
    2
  • 04735数据库系统原理(知识点整合)

    04735数据库系统原理(知识点整合)文章目录填空 1 文档存储的存储格式可以多样化 适合存储系统日志等 数据 非结构化 2 孤立点是指数据中与整体表现行为不一致的 数据集合 3 在 MySQL 中 只有使用了 的数据库或表才支持事务 InnoDB 引擎 4 一个锁实质上就是允许或阻止一个事务对一个数据对象的 存取特权 5 在 MySQL 中 实体完整性是通过主键约束和 约束来实现的 候选键 6 数据库的生命期可分为两个阶段 分别是数据库 数据库实现与操作阶段 分析与设计阶段 7 1986 年 10 月美国 ANSI 公布最早的 SQL 标准 1

    2026年3月17日
    2
  • 【Ubuntu安装 Nginx】「建议收藏」

    【Ubuntu安装 Nginx】「建议收藏」ubuntu安装nginx目前支持两种安装方式,一种是apt-get的方式,另一种是根据包安装的方式为方便我统一使用root用户一、apt-get安装nginx切换至root用户sudosurootapt-getinstallnginx如果安装时遇到这种情况,就输入sudoaptupdate在重新输入安装命令即可。查看nginx是否安装成功nginx-v启动nginxservicenginxstart启动后,在网页重输入ip地址,即可看到nginx的欢

    2026年1月25日
    5
  • Cursor+MCP实现用嘴操纵数据库,太丝滑了!

    Cursor+MCP实现用嘴操纵数据库,太丝滑了!

    2026年3月16日
    3
  • Java 深拷贝和浅拷贝 利用序列化实现深拷贝

    Java 深拷贝和浅拷贝 利用序列化实现深拷贝

    2021年8月21日
    58
  • MCMC采样_MCMC认证

    MCMC采样_MCMC认证MCMC(一)蒙特卡罗方法MCMC(二)马尔科夫链MCMC(三)MCMC采样和M-H采样MCMC(四)Gibbs采样在MCMC(三)MCMC采样和M-H采样中,我们讲到了M-H采样已经可以很好

    2022年8月5日
    11

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号