【NOIP2016提高组A组7.16】第三条跑道

题目

数据范围

分析

时限5000ms。
我们注意到\(a_{i}初始值以及x小于等于600且非零\)
也就是说,\(a_{i}\)的质因数一定小于600,而600以内的质因数只有109个。
那么考虑常用于区间修改的线段树。
用线段树来维护某个位置的某个质因数的总乘积,以及某个质因数出现的位置的个数。
时间复杂度\(O(QlogN·109)\)

#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
const long long maxlongint=2147483647;
const long long mo=100000007;
const long long N=50005;
using namespace std;
struct ddx
{
    long long a[120],v[120],lazy[120],sum[120];
}tree[50005];
long long ss[80000],n,m,ny[1000005],belong[1000005];
long long ans,re[10005];
bool b[1000005];
long long mi(long long x,long long y)
{
    long long sum=1;
    while(y)
    {
        if(y&1) sum=x*sum%mo;
        x=x*x%mo;
        y/=2;
    }
    return sum;
}
long long put(long long v,long long l,long long r,long long x,long long y,long long z)
{
    if(l==r)
    {
        tree[v].a[y]=z;
        tree[v].v[y]=tree[v].v[y]*mi(ss[y],z)%mo;
        tree[v].sum[y]=1;
        return 0;
    }
    long long mid=(l+r)/2;
    if(x<=mid)
        put(v*2,l,mid,x,y,z);
            else put(v*2+1,mid+1,r,x,y,z);
    for(long long i=1;i<=109;i++)
    {
        tree[v].a[i]=(tree[v*2].a[i]+tree[v*2+1].a[i])%mo;
        tree[v].v[i]=tree[v*2].v[i]*tree[v*2+1].v[i]%mo;
        tree[v].sum[i]=tree[v*2].sum[i]+tree[v*2+1].sum[i];
    }
}
long long down(long long v,long long mid,long long l,long long r,long long y)
{
    if(!tree[v].lazy[y]) return 0;
    long long z=tree[v].lazy[y];
    tree[v*2].a[y]+=z*(mid-l+1);
    tree[v*2+1].a[y]+=z*(r-mid);
    tree[v*2].v[y]=tree[v*2].v[y]*mi(ss[y],z*(mid-l+1))%mo;
    tree[v*2+1].v[y]=tree[v*2+1].v[y]*mi(ss[y],z*(r-mid))%mo;
    tree[v*2].lazy[y]+=z;
    tree[v*2+1].lazy[y]+=z;
    tree[v*2].sum[y]=(mid-l+1);
    tree[v*2+1].sum[y]=(r-mid);
    tree[v].lazy[y]=0;
}
long long change(long long v,long long l,long long r,long long x,long long x1,long long y,long long z)
{
    if(l==x && r==x1)
    {
        tree[v].a[y]=(tree[v].a[y]+z*(r-l+1))%mo;
        tree[v].v[y]=tree[v].v[y]*mi(ss[y],z*(r-l+1))%mo;
        tree[v].sum[y]=(r-l+1);
        tree[v].lazy[y]+=z;
        return 0;
    }
    long long mid=(l+r)/2;
    for(long long i=1;i<=109;i++) down(v,mid,l,r,i);
    if(x1<=mid)
        change(v*2,l,mid,x,x1,y,z);
    else
    if(x>mid)
        change(v*2+1,mid+1,r,x,x1,y,z);
    else
        change(v*2,l,mid,x,mid,y,z),change(v*2+1,mid+1,r,mid+1,x1,y,z);
    for(long long i=1;i<=109;i++)
    {
        tree[v].a[i]=(tree[v*2].a[i]+tree[v*2+1].a[i])%mo;
        tree[v].v[i]=tree[v*2].v[i]*tree[v*2+1].v[i]%mo;
        tree[v].sum[i]=tree[v*2].sum[i]+tree[v*2+1].sum[i];
    }
}
long long find(long long v,long long l,long long r,long long x,long long x1)
{
    if(l==x && r==x1)
    {
        for(long long i=1;i<=109;i++)
        {
            if(tree[v].sum[i])
                ans=ans*tree[v].v[i]%mo*mi(ny[ss[i]],tree[v].sum[i])%mo*mi(ss[i]-1,tree[v].sum[i])%mo;
        }
        return 0;
    }
    long long mid=(l+r)/2;
    for(long long i=1;i<=109;i++) down(v,mid,l,r,i);
    if(x1<=mid)
        find(v*2,l,mid,x,x1);
    else
    if(x>mid)
        find(v*2+1,mid+1,r,x,x1);
    else
        find(v*2,l,mid,x,mid),find(v*2+1,mid+1,r,mid+1,x1);
    for(long long i=1;i<=109;i++)
    {
        tree[v].a[i]=(tree[v*2].a[i]+tree[v*2+1].a[i])%mo;
        tree[v].v[i]=tree[v*2].v[i]*tree[v*2+1].v[i]%mo;
        tree[v].sum[i]=tree[v*2].sum[i]+tree[v*2+1].sum[i];
    }
}
int main()
{
    memset(b,true,sizeof(b));
    b[0]=0;
    b[1]=0;
    for(long long i=2;i<=10000;i++)
    {
        if(b[i])
        {
            ss[++ss[0]]=i;
            ny[i]=mi(i,mo-2);
            belong[i]=ss[0];
        }
        for(long long j=1;j<=ss[0];j++)
        {
            if(i*ss[j]<=10000)
                b[i*ss[j]]=false;
                    else break;
            if(!(i%ss[j])) break;
        }
    }
    scanf("%lld",&n);
        for(long long i=1;i<=50001;i++)
            for(long long j=1;j<=110;j++)
                tree[i].v[j]=1;
        for(long long j=1;j<=n;j++)
        {
            scanf("%lld",&re[j]);
            long long p=re[j];
            if(b[p])
            {
                put(1,1,n,j,belong[p],1);
            }
            else
            {
                for(long long k=1;ss[k]<=sqrt(re[j]) && p>1;k++)
                {
                    long long w=0;
                    while(!(p%ss[k]))
                    {
                        p/=ss[k];
                        w++;
                    }
                    if(w)
                    {
                        put(1,1,n,j,k,w);
                    }
                }
                if(p>1)
                {
                    put(1,1,n,j,belong[p],1);
                }
            }
        }
        long long q;
        scanf("%lld",&q);
        for(long long i=1;i<=q;i++)
        {
            long long t,x,y,z;
            scanf("%lld%lld%lld",&t,&x,&y);
            if(t)
            {
                ans=1;
                find(1,1,n,x,y);
                printf("%lld\n",ans);
            }
            else
            {
                scanf("%lld",&z);
                long long p=z;
                if(b[p])
                {
                    change(1,1,n,x,y,belong[p],1);
                }
                else
                {
                    for(long long k=1;ss[k]<=sqrt(z) && p>1;k++)
                    {
                        long long w=0;
                        while(!(p%ss[k]))
                        {
                            p/=ss[k];
                            w++;
                        }
                        if(w)
                        {
                            change(1,1,n,x,y,k,w);
                        }
                    }
                    if(p>1)
                    {
                        change(1,1,n,x,y,belong[p],1);
                    }
                }
            }
        }
}

原文地址:https://www.cnblogs.com/chen1352/p/9013519.html

时间: 2024-08-29 06:54:08

【NOIP2016提高组A组7.16】第三条跑道的相关文章

JZOJ 4638 第三条跑道 【NOIP2016提高组A组7.16】

第三条跑道 该题目的名字是一首歌 题目大意 输入格式 输出格式 对于每个询问,单独一行输出答案. 样例输入 5 2 3 4 5 6 3 1 1 5 0 2 3 6 1 2 3 样例输出 32 48 数据范围 题解 我们先看一下φ的通式. 其中p1, p2--pn为x的所有质因数,x是不为0的整数. 再看一下数据范围,,这也就意味着ai在任何时刻都满足它的素因子是600以内的,而φ(ai)只跟它的素因子有关. 因为是区间查询/修改,当然是开线段树了. 600以内的素因子有109个,所以我们就种10

判断用户的用户名和其基本组的组名是否一致

#!/bin/bash #传递一个用户名参数给脚本,判断此用户的用户名跟其基本组的组名是否一致,并将结果显示出来 #判断是否传递一个参数 if [ ! $# -eq 1 ]; then echo "Usage:./group.sh ARG" exit 1 fi #判断是否存在该用户 id $1 &> /dev/null if [ ! $? -eq 0 ]; then echo "$1 not exits." exit 1 fi #取给定用户所属基本组i

NFC模组,开发NFC功能 只要几条指令的事情

支持WIN8/WIN7 + android + wince +MCU 单片机 + linux + MAC  ...... 兼融所有平台,只要你会串口编程! SMC532模组,是一个集成了MCU+NFC的模组,采用了使用最为广泛的NFC芯片NXP的PN532作为NFC底层通信链路,保证了可靠性的兼容性,然后,MCU采用了ARM-M3的工业级(兼容军工级)单片机STM32作为主控,风火轮科技工程师倾注大量心血嵌入了完整高效的NFC应用协议栈,使得用户在开发NFC功能应用时更为简单,   只需要简单的

tableView组头 组尾滑动

今天布局tableview 要组头组尾滑动 从网上找的代码 很实用 留下来 每天进步一下 - (void)scrollViewDidScroll:(UIScrollView *)scrollView { if (scrollView == self.detailsTableView) { UITableView *tableview = (UITableView *)scrollView; CGFloat sectionHeaderHeight = 50; CGFloat sectionFoot

linux用户和组 只 组的管理

1. groupadd 新建组, 组名最长不能超过32个字节 groupadd -create a new group 语法: groupadd [option] 组名 -g, --gid GID        指定GID -r, --system          创建一个系统组 -o, --non-unique   此选项允许添加一个使用非唯一GID的组 [[email protected] ~]# groupadd admin [[email protected] ~]# groupadd

组播初涉,用户如何知道想加入哪一个组播组,如何知道要加入哪一个组播地址?

刚学到组播的时候,纠结了一个问题,用户如何知道想加入哪一个组播组,如何知道要加入哪一个组播地址? 现在想想真是,用四个字来形容就是我作为一个学计算机的“不够专业”. 这个问题其实很好回答,只是没想清楚而已,其实他等价于一个问题,我在看网页,发qq的时候,看B站的时候,我的手机是如何知道对方的IP地址从而获取数据的呢? 哈哈哈哈哈哈,那就是,码农们已经给你写好了,你用的软件其实到哪获取数据都已经是被写进去了,比如,腾讯的服务器是xxxx,你发qq的时候手机根据写好的程序 就自动与xxxx联系了.

【《Effective C#》提炼总结】提高Unity中C#代码质量的22条准则

本文由@浅墨_毛星云 出品,转载请注明出处.   文章链接:http://blog.csdn.net/poem_qianmo/article/details/53869998 作者:毛星云(浅墨)    微博:http://weibo.com/u/1723155442 引言 我们知道,在C++领域,作为进阶阅读材料,必看的书是<Effective C++>. 而<Effective C#>之于C# ,是类似<Effective C++>之于C++一样的存在. 这篇文章,

提高工作效率:给设计师的10条建议

这篇文章虽然原本是”写给自由设计师的10条建议”.但仔细读下来,发现对于坐班的设计师人来说,也很有价值.提高效率,收获更好的成果. 对于很多人来说,自由工作是梦寐以求的事.能够自由分配时间,无人监督,听起来就很棒. 实际上,在家工作容易缺少动力,而且很多事情容易让你分心,自制力不强的人当不好自己的老板,无法有效的进行个人管理.同样的,自由设计师也有相似的问题. 一般自由设计师都会列出一堆待办事项,面对长长的列表,很多人感叹工作多得做不完,因此压力很大.下面是几条小建议,让你的自由工作”有章可循”

JZOJ 4639 Angel Beats!【NOIP2016提高组A组7.16】

Angel Beats! (这是一部日漫,7.16的出题人好神奇,名字都来自于影音作品) 题目大意 给你一棵1为根的树,然后会有q个询问,向你查询点x子树和点y子树的重心,重心可能会有很多个,你只需要输出距离和即可. 两棵子树的重心的定义如下:在树上找到一个点,使得该点到两棵子树中所有点距离之和最小,即这两棵子树的重心. 输入格式 第一行一个整数 ,代表点的数量. 接下来 n-1行,第i 行的表示节点i 的父亲节点. 接下来一个整数q ,为询问的个数. 接下来q 行,每行两个数x,y ,表示查询