hdu 4407 容斥原理

参考https://blog.csdn.net/qq_15714857/article/details/47954263

题意:

给一个长度为n的序列,序列由1~n依次组成。
对序列执行两种操作:
1.查询[x,y]内与p互素的数的和;
2.修改第x个数为c.

思路:

2修改操作用map进行映射。

查询时,把序列一直当做1~n的序列来查询,然后迭代器跑一遍map判断对查询有无影响;
对于查询操作,我们可以先分解出p的质因数,设p的每种质因数组合的里的质因数乘积为value,那么[x,y]内value的倍数与p必定不互素,求出value的区间[x,y]内所有倍数和(用等比数列求和公式cal()),然后对结果进行容斥求和,即得出区间[x,y]内与p不互素的数的和sum,然后区间所有数的和(用等差数列求和公式)减去sum即可。

代码:

#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
#include<cstdlib>
#include<map>
#include<algorithm>
using namespace std;
#define N 2300010
#define ll long long
const int maxn=30005;
const ll mod=1000000007;
map<int,int>v;
vector<int>fac;
int gcd(int x,int y)
{
    if(y==0) return x;
    return gcd(y,x%y);
}
ll cal( int l , int r , int val ){//l-r区间val的倍数的和
    int n = ( r / val ) - ( ( l - 1 ) / val ) ;
    int a1 = ( l % val == 0 )? l : ( val - l % val ) + l ;
    int an = r - r % val ;
    ll res = (ll)( a1 + an ) * (ll)n / 2 ;
    return res ;
}
ll work(int l,int r,int p)
{
    fac.clear();
    for(int i=2;i*i<=p;i++)
    {
        if(p%i==0)
        {
            fac.push_back(i);
            while(p%i==0) p/=i;
        }
    }
    if(p>1) fac.push_back(p);//获得p的质因子
    int s=fac.size();
    ll res=0;
    for(int i=1;i<(1<<s);i++)
    {
        int bits=0;
        ll val=1;
        for(ll j=0;j<s;j++)
        {
            if(i&(1<<j))
            {
                bits++;
                val*=fac[j];
            }
        }
        ll tmp=cal(l,r,val);
        if(bits&1) res+=tmp;//容斥
        else res-=tmp;
    }
    ll sum=(ll)(l+r)*(ll)(r-l+1)/2;
    res=sum-res;
    return res;
}
ll solve(int l,int r,int p)
{
    ll res=work(l,r,p);
    if(v.empty()) return res;
    map<int,int>::iterator it;
    for(it=v.begin();it!=v.end();it++)
    {
        ll x=it->first,y=it->second;
        if(x>r||x<l) continue;
        if(gcd(x,p)==1)res-=x;
        if(gcd(y,p)==1) res+=y;
    }
    return res;
}
int main(){
    int op,n,m,t,x,y,p;
    scanf("%d",&t);
    while(t--)
    {
        v.clear();
        scanf("%d%d",&n,&m);
        for(int i=0;i<m;i++)
        {
            scanf("%d",&op);
            if(op==1)
            {
                scanf("%d%d%d",&x,&y,&p);
                if(x>y) swap(x,y);
                ll ans=solve(x,y,p);
                printf("%lld\n",ans);
            }
            else
            {
                scanf("%d%d",&x,&y);
                v[x]=y;
            }
        }
    }
    return 0;
}

 

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可私 6信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可 6私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可私 6信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值