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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 多项式回归

    多项式回归

    2021年11月15日
    64
  • IDEA继承父类后重写方法快捷键

    IDEA继承父类后重写方法快捷键eg:我们的MyServlet继承了HttpServlet,我们想要重写里面的doGet()方法和doPost()方法,如何做到呢?publicclassMyServletextendsHttpServlet{}1)ctrl+o,注意光标在继承的父类名后2)弹出下图后3)我们想要选定连续的方法怎么做?按住shift键,默认开始为当前位置,结束位置为你下次的鼠标单击位置4)我们只是想选择不连续的两个方法,比如说上文的doGet()和doPost(),如何做.

    2025年6月14日
    7
  • 关于设计WAP网站缩放的问题

    关于设计WAP网站缩放的问题设计 WAP 网站是 请一定要在缩放比例为 1 0 下进行设计 否则就会出现博主现在遇到的情况 1 点击输入框页面会放大 想解决就去设置 VIEW 但是固定了缩放比例 WAP 就不能自动适应其他手机了

    2025年10月9日
    5
  • Python读写excel表格的方法一

    Python读写excel表格的方法一

    2022年3月4日
    56
  • xshell连接虚拟机步骤_建立主机与vm虚拟机的网络连接

    xshell连接虚拟机步骤_建立主机与vm虚拟机的网络连接Xshell连接虚拟机1、打开虚拟机终端,输入下面命令,找到ens33对应的IP地址,如图ifconfig2、打开Xshell,打开文件–>新建3、填写名称,主机这里填入刚才的IP,点击连接4、输入登录的用户名,点击确定5、输入密码,点击确定6、连接成功,可以开始使用…

    2022年4月19日
    69
  • 软RAID1 更换坏硬盘

    软RAID1 更换坏硬盘1 买块容量一样大小的硬盘 2 把新买的硬盘安装到机器了 3 分区硬盘并把 t 的类型设为 fd 我新添加的硬盘盘符为 dev sdb fdisk dev sdb4 运行 partprobe 让内核重新装载分区表 5 停止 RAID1 的挂载 umount dev md06 移除损坏的设备 mdadm dev md0 r de

    2025年8月4日
    3

发表回复

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

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