• HDU 4407 SUM 容斥原理


    这个题目要求既对序列的某段区间求和p互质数目,又支持对某个数进行修改

    一开始看到这个题,有点懵,就是因为第二个操作,如果只是第一个操作,并且是原始序列1-n,那就很简单了,按照之前写过的某个题目,求出1-y中的数目,减去1-x中的数目即可

    就是第二个操作把序列打乱了,这样就不好搞了

    后来还是大神博客的一句话,突然解决了问题,说:总的操作数只有1000,直接暴力搞定第二个操作就行啊

    我想想,对啊,一开始只是按普通操作求出数目,然后遍历一下修改(都最多只有1000个),把修改对应投射到结果上,就行了啊。。。于是,迎仍而解。。。

    怎么没想到可以暴力呢,太把第二个操作当回事了

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #define LL __int64
    using namespace std;
    const int N = 400010;
    int change[N],n,m;
    int calc[1010],cnt;
    int prime[20],ret;
    int gcd(int a,int b)
    {
        if (a<b) swap(a,b);
        while (b)
        {
            int tmp=b;
            b=a%b;
            a=tmp;
        }
        return a;
    }
    void proc(int x)
    {
        ret=0;
        for (int i=2;i*i<=x;i++){
            if (x%i==0){
              prime[ret++]=i;
              while (x%i==0) x/=i;
            }
        }
        if (x>1) prime[ret++]=x;
    }
    LL dfs(int d,int co,int sign,int x)
    {
        if (d>=ret) return 0;
        LL sum=0;
        if (d>=0){
            LL res=x/co;
            if (res>0)
            sum=(LL)res*co+res*(res-1)/2*co;
            sum*=(LL)sign;
        }
        for (int i=d+1;i<ret;i++){
            sum+=dfs(i,co*prime[i],-sign,x);
        }
        return sum;
    }
    int main()
    {
        int t,x,y,p,op;
        scanf("%d",&t);
        while (t--)
        {
            scanf("%d%d",&n,&m);
            //memset(change,0,sizeof(change[0]*(n+2)));
            cnt=0;
            while (m--)
            {
                scanf("%d",&op);
                if (op==2){
                    scanf("%d%d",&x,&y);
                    change[x]=y;
                    bool flag=0;
                    for (int i=0;i<cnt;i++){
                        if (calc[i]==x) {flag=1;break;}
                    }
                    if (!flag) calc[cnt++]=x;
                }
                else{
                    scanf("%d%d%d",&x,&y,&p);
                    if (x>y) swap(x,y);
                    proc(p);
                    LL sum1=dfs(-1,1,-1,x-1);
                    LL sum2=dfs(-1,1,-1,y);
                    //cout<<sum1<<" "<<sum2<<endl;
                    sum2-=sum1;
                    LL all=(LL)(x+y)*(y-x+1)/2;
                    all-=sum2;
                    for (int i=0;i<cnt;i++){
                        if (calc[i]>=x && calc[i]<=y){
                            if (gcd(calc[i],p)==1) all-=(LL)calc[i];
                            if (gcd(change[calc[i]],p)==1) all+=(LL)change[calc[i]];
                        }
                    }
                    printf("%I64d
    ",all);
                }
            }
        }
    }
    

      

  • 相关阅读:
    递归树结构封装
    Excel父子数据导入
    资产类标准数据源抽取顺序
    资产模型数据初始化时应注意的事项
    Input Parameters and Variables in SAP HANA Modeling
    2LIS_03_BX数据源的用处及抽取步骤
    BW资产数据源抽取顺序
    MM物料移动BW数据源介绍
    关于BW newGL datasource
    使用SLT系统抽数到hana系统
  • 原文地址:https://www.cnblogs.com/kkrisen/p/3961535.html
Copyright © 2020-2023  润新知