hdu4407 Sum 容斥+暴力

http://acm.hdu.edu.cn/showproblem.php?pid=4407

Sum

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1990    Accepted Submission(s): 564

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

2012 ACM/ICPC Asia Regional Jinhua Online

题意:对于1到n的n个数,两种操作,一种是第[x,y]区间有多少数和p互质,另一种是改变第x个数为c。

分析:如果没有第二个操作,那么求[x,y]区间可以直接用容斥求1到x-1和1到y的分别有多少个与p互质的,结果一减就好。对于操作2,由于总操作数只有m<=1000次,那么我们可以用一个map记录修改的数,然后暴力扫一遍map每一个数,map[a]=b,若a在区间[x,y]内,a与p互质,则答案减1,b与p互质则加1.。。

/**
 * @author neko01
 */
//#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
#include <cmath>
#include <set>
#include <map>
using namespace std;
typedef long long LL;
#define min3(a,b,c) min(a,min(b,c))
#define max3(a,b,c) max(a,max(b,c))
#define pb push_back
#define mp(a,b) make_pair(a,b)
#define clr(a) memset(a,0,sizeof a)
#define clr1(a) memset(a,-1,sizeof a)
#define dbg(a) printf("%d\n",a)
typedef pair<int,int> pp;
const double eps=1e-9;
const double pi=acos(-1.0);
const int INF=0x7fffffff;
const LL inf=(((LL)1)<<61)+5;
int n,m;
const int M=1000;
bool isprime[M];
int prime[M];
int fac[25];
int tot=0,num;
map<int,int>mp;
map<int,int>::iterator it;
int gcd(int a,int b)
{
    return b==0?a:gcd(b,a%b);
}
void getprime()
{
    for(int i=2;i<=M;i++)
    {
        if(isprime[i]) continue;
        prime[tot++]=i;
        for(int j=i*i;j<=M;j+=i)
            isprime[j]=true;
    }
}
LL gao(int x)
{
    LL sum=0;
    for(int i=1;i<(1<<num);i++)
    {
        int tmp=1,op=0;
        for(int j=0;j<num;j++)
        {
            if((1<<j)&i)
            {
                op++;
                tmp*=fac[j];
            }
        }
        if(op&1)
        {
            LL k=x/tmp;
            sum+=(tmp+k*tmp)*k/2;
        }
        else
        {
            LL k=x/tmp;
            sum-=(tmp+k*tmp)*k/2;
        }
    }
    return 1LL*x*(1+x)/2-sum;
}
void getfac(int x)
{
    num=0;
    for(int i=0;i<tot&&prime[i]*prime[i]<=x;i++)
    {
        if(x%prime[i]==0)
        {
            fac[num++]=prime[i];
            while(x%prime[i]==0)
                x/=prime[i];
        }
    }
    if(x>1) fac[num++]=x;
}
LL getans(int a,int b,int p)
{
    LL ans=gao(b)-gao(a-1);
    for(it=mp.begin();it!=mp.end();it++)
    {
        if(it->first<a||it->first>b||it->first==it->second)
            continue;
        if(gcd(it->first,p)==1) ans-=it->first;
        if(gcd(it->second,p)==1) ans+=it->second;
    }
    return ans;
}
int main()
{
    int t;
    scanf("%d",&t);
    getprime();
    while(t--)
    {
        scanf("%d%d",&n,&m);
        mp.clear();
        for(int i=1;i<=m;i++)
        {
            int xx,x,y,p;
            scanf("%d",&xx);
            if(xx==1)
            {
                scanf("%d%d%d",&x,&y,&p);
                getfac(p);
                printf("%I64d\n",getans(x,y,p));
            }
            else
            {
                scanf("%d%d",&x,&y);
                mp[x]=y;
            }
        }
    }
    return 0;
}
时间: 2024-10-05 04:41:14

hdu4407 Sum 容斥+暴力的相关文章

hdu 4407 Sum 容斥+离线

求X-Y之间和p互质的数的和,典型的容斥问题,求和用等差数列求和,注意首项末项是多少. 首先记录下不修改的答案,离线处理,存下询问,输出的时候,遇到一个操作1,就遍历前面的操作,把修改加上去,注意要判重,只保留最后一次修改. #include <stdio.h> #include <vector> #include <algorithm> #include <cmath> #include <iostream> #include<cstri

hdu 4407 Sum(容斥)

http://acm.hdu.edu.cn/showproblem.php?pid=4407 起初有n个数1~n,这里有m个操作,两种类型.操作1:求出[x,y]区间内与p互质的数的和.操作2:将第x位置的数变成y.对于每一个询问,输出结果. 因为只有1000次操作,而且起初是有序的.那么对于第i个询问,我们先忽略i之前的所有的第2种操作,即认为n个数为1~n,根据容斥原理求出[x,y]区间内与p互质的数之和,然后遍历i之前的操作2,对所求的答案进行调整即可.wa了无数次,改了好久,是因为我忽略

数论 + 容斥 - HDU 4059 The Boss on Mars

The Boss on Mars Problem's Link Mean: 给定一个整数n,求1~n中所有与n互质的数的四次方的和.(1<=n<=1e8) analyse: 看似简单,倘若自己手动推公式的话,还是需要一定的数学基础. 总的思路:先求出sum1=(1^4)+(2^4)+...(n^4),再求出sum2=(1~n中与n不互质的数的四次方的和),answer=sum1-sum2. 如何求sum1呢? 有两种方法: 1.数列差分.由于A={Sn}={a1^4+a2^4+...an^4}

GCD SUM 强大的数论,容斥定理

GCD SUM Time Limit: 8000/4000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) SubmitStatus Problem Description 给出N,M执行如下程序:long long  ans = 0,ansx = 0,ansy = 0;for(int i = 1; i <= N; i ++)   for(int j = 1; j <= M; j ++)       if(gcd(i,j)

hdu 5514 Frogs(容斥)

Frogs Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1315    Accepted Submission(s): 443 Problem Description There are m stones lying on a circle, and n frogs are jumping over them.The stones a

【BZOJ4559】[JLoi2016]成绩比较 动态规划+容斥+组合数学

[BZOJ4559][JLoi2016]成绩比较 Description G系共有n位同学,M门必修课.这N位同学的编号为0到N-1的整数,其中B神的编号为0号.这M门必修课编号为0到M-1的整数.一位同学在必修课上可以获得的分数是1到Ui中的一个整数.如果在每门课上A获得的成绩均小于等于B获得的成绩,则称A被B碾压.在B神的说法中,G系共有K位同学被他碾压(不包括他自己),而其他N-K-1位同学则没有被他碾压.D神查到了B神每门必修课的排名.这里的排名是指:如果B神某门课的排名为R,则表示有且

「总结」容斥。二.反演原理

二.反演原理 0.综述 说一下个人对反演的理解. 反演是一种手段,一种处理已知信息和未知信息关系的手段,用来得到未知信息的方式.也就是以一种既定的手段在较小的时间复杂度内用已知的信息得到未知的信息. 还有$zsq$学长更加浅显的解读. 反演一般就是把一个好看但难算的式子转化成一个难看且难算的式子在转化为一个难看但好算的式子. 先来一个裸一点的反演 下面要说我知道的四种反演. 子集反演,针对的是集合交并的容斥. 二项式反演,针对组合原理的容斥. 莫比乌斯反演,针对约数和倍数的容斥. 斯特林反演,针

POJ 2773 Happy 2006 二分+容斥(入门

题目链接:点击打开链接 题意: 输入n ,k 求与n互质的第k个数(这个数可能>n) 思路: solve(mid)表示[1,mid]中有多少个和n互质,然后二分一下最小的mid 使得互质个数==k solve(x) 实现: 与n互质的个数=所有数-与n不互质的数=所有数-(与n有一个因子-与n有2个因子的+与n有3个因子的) 状压n的因子个数,然后根据上面的公式容斥得到. #include <stdio.h> #include <iostream> #include <

[coci2011]友好数对 容斥

无趣的小x在玩一个很无趣的数字游戏.他要在n个数字中找他喜欢友好数对.他对友好数对的定义是:如果有两个数中包含某一个以上相同的数位(单个数字),这两个数就是友好数对.比如:123和345 就是友好数对,因为都包含数位3,显然123和234也是由号数对.而12和34则不是友好数对,因为它们没有相同的数位. 刚拿到题没怎么读懂,因为我直观的想法是存一下扫一遍就行了,后来一想,得用容斥:又犯蠢了: 其实这道题的容斥比较基本,看代码吧: #include<iostream> #include<c