UESTC 1712 E Easy Problem With Numbers 线段树+互质也可以求逆元

/*
*Rainto96
*Beijing University of Posts and Telecommunications School of Software Engineering
*http://blog.csdn.net/u011775691
http://www.bnuoj.com/v3/problem_show.php?pid=24253
n个数,m个操作
1.查询区间积
2.区间中每个数乘x
3.区间中每个数除x
坑:
1.将一个数分解成M的相关质数×某数时候,注意该数为0的情况
2. 0可以除以任何数,然后M质数频数表项可能为负数,小心qPow会停不下来。可以处理为,qPow(a,n)发现n<0则return 0,因为接下来的操作中,0位肯定还是0不会变
*/
#include <ctime>
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring>
#include <string>
#include <cmath>
#include <set>
#include <map>
#include <vector>
#include <climits>
#include <cassert>
using namespace std;
#define pb push_back
#define ALL(x) x.begin(),x.end()
#define VINT vector<int>
#define PII pair<int,int>
#define MP(x,y) make_pair((x),(y))
#define ll long long
#define ull unsigned ll
#define MEM0(x)  memset(x,0,sizeof(x))
#define MEM(x,val) memset((x),val,sizeof(x))
#define scan(x) scanf("%d",&(x))
#define scan2(x,y) scanf("%d%d",&(x),&(y))
#define scan3(x,y,z) scanf("%d%d%d",&(x),&(y),&(z))
#define scan4(x,y,z,k) scanf("%d%d%d%d",&(x),&(y),&(z),&(k))
#define Max(a,b) a=max(a,b)
#define Min(a,b) a=min(a,b)
using namespace std;

//******************************
//返回d=gcd(a,b);和对应于等式ax+by=d中的x,y
long long extend_gcd(long long a,long long b,long long &x,long long &y)
{
    if(a==0&&b==0) return -1;//无最大公约数
    if(b==0){x=1;y=0;return a;}
    long long d=extend_gcd(b,a%b,y,x);
    y-=a/b*x;
    return d;
}
//*********求逆元素*******************
//ax = 1(mod n)
long long mod_reverse(long long a,long long n)
{
    long long x,y;
    long long d=extend_gcd(a,n,x,y);
    if(d==1) return (x%n+n)%n;
    else return -1;
}

const long long UP=66666;
int prm[UP+10];
bool visP[UP+10];
int pn;
void getPrm(){
        for(int i=2;i<=UP;i++){
                if(!visP[i]){
                        prm[pn++]=i;
                        for(int j=i;j<=UP;j+=i) visP[j]=true;
                }
        }
}
//--------------------------------------------------------------------
int n,M;
const int MAXN = 10111;
int f[MAXN];
int Mprm[66];
int CNT=0;
int qPow(int a,int n){
        //cerr<<a<<" "<<n<<endl;
        //n=abs(n);
        //assert(n>=0);
        int sum=1;
        int now=a;
        while(n){
                if(n&1) sum=1LL*sum*now%M;
                now=1LL*now*now%M;
                n>>=1;
        }
        return sum;
}

int qPow2(int a,int n){
        //cerr<<a<<" "<<n<<endl;
        //n=abs(n);
        if(n<0) return 0;
        //assert(n>=0);
        int sum=1;
        int now=a;
        while(n){
                if(n&1) sum=1LL*sum*now%M;
                now=1LL*now*now%M;
                n>>=1;
        }
        return sum;
}
struct Vector{
    int v[10];
    Vector(){
        memset(v,0,sizeof(v));
    }
    Vector operator + (const Vector& s){
        Vector tt = *this;
        for(int i=0;i<CNT;i++) {
            tt.v[i] += s.v[i];
            //assert(tt.v[i] >= 0);
        }
        return tt;
    }
    Vector operator * (const int num){
        Vector tt = *this;
        for(int i=0;i<CNT;i++) tt.v[i] *= num;
        return tt;
    }

    int getValue(){
        int val = 1;
        for(int i=0;i<CNT;i++) val = 1LL * val * qPow2(Mprm[i] , v[i]) % M;
        return val;
    }
    void clear(){
        for(int i=0;i<CNT;i++) v[i] = 0;
    }
    void fu(){
        for(int i=0;i<CNT;i++) v[i] = -v[i];
    }
    void print(){
        for(int i=0;i<CNT;i++) printf("%d " , v[i]);
        cout<<endl;
    }
};



void makeMprm(){
    CNT=0;
    int tmp=M;
    for(int i=0;i<pn && prm[i] * prm[i] <= tmp;i++){
        if(tmp%prm[i] == 0){
            Mprm[CNT++] = prm[i];
            while( tmp%prm[i] == 0 ){
                tmp /= prm[i];
            }
        }
    }
    if(tmp!=1) Mprm[CNT++] = tmp;
}
#define PIV pair<int ,Vector >
pair<int ,Vector > trans(int x){
    //cerr<<"In trans:"<<x;

    Vector vec;
    for(int i=0;i<CNT;i++){
        while(x!=0 && x % Mprm[i] == 0) {
            x/= Mprm[i];
            vec.v[i] ++;
        }
    }
    //cerr<<" -> "<<x<<" ";
    //vec.print();

    return MP(x,vec);
}







#define lson(x) (x)<<1
#define rson(x) (x)<<1|1
struct Node {
	int l, r , val ,len;
	Vector V;
	bool lazy;
	int lazyval;
	Vector lazyV;
};
struct Seg{
	Node  node[MAXN * 6];
    void pushup(int x) {
        node[x].V = node[lson(x)].V + node[rson(x)].V;
        node[x].val = 1LL * node[lson(x)].val * node[rson(x)].val % M;
    }
    void pushdown(int x) {
        if (node[x].lazy) {
            node[lson(x)].lazyV =node[lson(x)].lazyV + node[x].lazyV;
            node[lson(x)].V =node[lson(x)].V + node[x].lazyV * node[lson(x)].len;
            node[rson(x)].lazyV =node[rson(x)].lazyV + node[x].lazyV;
            node[rson(x)].V =node[rson(x)].V + node[x].lazyV * node[rson(x)].len;

            node[lson(x)].lazyval =1LL * node[lson(x)].lazyval * node[x].lazyval % M;
            node[lson(x)].val =1LL * node[lson(x)].val * qPow(node[x].lazyval , node[lson(x)].len) % M;
            node[rson(x)].lazyval =1LL * node[rson(x)].lazyval * node[x].lazyval % M;
            node[rson(x)].val =1LL * node[rson(x)].val * qPow(node[x].lazyval , node[rson(x)].len) % M;



            node[lson(x)].lazy = true;
            node[rson(x)].lazy = true;
            node[x].lazy = false;
            node[x].lazyval=1;
            node[x].lazyV.clear();
        }
    }

    void build(int l, int r, int x = 1) {
        node[x].l = l; node[x].r = r; node[x].lazy = false;
        node[x].V.clear();
        node[x].lazyV.clear(); node[x].lazyval=1; node[x].len = r-l+1;
        if (l == r) {
            PIV p = trans(f[l]);
            node[x].val = p.first % M;
            node[x].V = p.second;
            return;
        }
        int mid = (l + r) / 2;
        build(l, mid, lson(x));
        build(mid + 1, r, rson(x));
        pushup(x);
    }

    void update(int l, int r,PIV& piv , int x = 1) {
        if (node[x].l >= l && node[x].r <= r) {
            node[x].lazy = true;
            node[x].lazyV = node[x].lazyV + piv.second;
            node[x].V = node[x].V + piv.second * node[x].len;
            node[x].val = 1LL * node[x].val *qPow(piv.first,node[x].len) % M;
            node[x].lazyval = 1LL * node[x].lazyval * piv.first % M;

            return;
        }
        int mid = (node[x].l + node[x].r) / 2;
        pushdown(x);
        if (l <= mid) update(l, r,piv, lson(x));
        if (r > mid) update(l, r,piv, rson(x));
        pushup(x);
    }

    int query(int l, int r, int x = 1) {
        if (node[x].l >= l && node[x].r <= r) {
            return 1LL * node[x].val * node[x].V.getValue() % M;
        }
        int mid = (node[x].l + node[x].r) / 2;
        pushdown(x);
        int ans = 1;
        if (l <= mid) ans = 1LL * ans * query(l, r, lson(x)) % M;
        if (r > mid) ans = 1LL * ans * query(l, r, rson(x)) % M;
        pushup(x);
        return ans;
    }
    void print(int l,int r,int x=1){
        cerr<<"point:"<<x<<endl;
        cerr<<"l:"<<node[x].l <<"r:"<<node[x].r<<endl;
        cerr<<"val:"<<node[x].val<<endl;
        cerr<<"TrueVal:"<<node[x].val * node[x].V.getValue() %M<<endl;
        cerr<<"V:";node[x].V.print();
        cerr<<"lazyV:";node[x].lazyV.print();
        cerr<<"bool:"<<node[x].lazy<<endl;
        cerr<<endl;
        if (l == r) {
            return;
        }
        int mid = (l + r) / 2;
        print(l, mid, lson(x));
        print(mid + 1, r, rson(x));
    }
}seg;

int main2(){
    freopen("/home/bupt110/in.txt","w",stdout);
    srand((int)time(NULL));
    int T = 15;
    cout<<T<<endl;
    while(T--){
        int n = 10000;
        int Q = 10000;
        int M = rand()%(int)((1e9-1) + 1);
        cout<<n<<" "<<M<<endl;
        for(int i=1;i<=n;i++){
            cout<<rand()%(int)((1e9-1) + 1) <<" ";
        }
        cout<<endl;
        cout<<Q<<endl;
        for(int i=1;i<=Q;i++){
            int kd=rand()%3;
            int l=rand()%10000+1 , r = rand()%10000+1;
            while(r<l) r = rand() % 10000 + 1;

            if(kd==0){
                cout<<'Q'<<" "<<l<<" "<<r<<endl;
            }else if(kd==1){
                cout<<'M'<<" "<<l<<" "<<r<<" "<< rand()%(int)((1e9-1) + 1) <<endl;
            }else{
                cout<<'D'<<" "<<l<<" "<<r<<" "<< rand()%(int)((1e9-1) + 1) <<endl;
            }
        }
    }
}

int main(){
	//freopen("/home/bupt110/in.txt","r",stdin);

	getPrm();
    int T;scan(T);
    for(int Cas = 1;Cas <= T;Cas++){
        printf("Case #%d:\n",Cas);
        scan2(n,M);
        makeMprm();
        for(int i=1;i<=n;i++) scan(f[i]);
        seg.build(1,n);
        int q;
        scan(q);
        while(q--){
            char str[33];
            scanf("%s",str);
            int l,r;
            scan2(l,r);
            int len = r-l+1;
            if(str[0] == 'Q'){
                int res = seg.query(l,r);
                printf("%d\n",res);
            }else if(str[0] == 'D'){
//                cerr<<"--------------------------"<<endl;
//                seg.print(1,n);
//                cerr<<endl;

                int x;scan(x);
                PIV piv = trans(x);
                //cerr<<piv.first<<":";
                piv.first = mod_reverse(piv.first, M);
                piv.second.fu();
                seg.update(l,r,piv);

//                cerr<<"--------------------------"<<endl;
//                seg.print(1,n);
//                cerr<<endl;
                //cerr<<"D:";piv.second.print();

            }else if(str[0] == 'M'){
//                cerr<<"--------------------------"<<endl;
//                seg.print(1,n);
//                cerr<<endl;
                int x;scan(x);
                PIV piv = trans(x);
                seg.update(l,r,piv);
//                cerr<<"--------------------------"<<endl;
//                seg.print(1,n);
//                cerr<<endl;
            }
        }
    }
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值