玲珑杯 1153 - 无影的神之右手 莫队

题目链接:http://www.ifrog.cc/acm/problem/1153

1153 - 无影的神之右手

Time Limit:4s Memory Limit:512MByte

Submissions:183Solved:14

DESCRIPTION




觉不觉得这几个图很有毒啊?
其实这几个不算很有毒吧~
由乃懒得写题面了,反正写了也没人看,所以直接说题意吧~
给你一个序列a,每次查询一个区间[l,r]的乘积的约数个数mod 19260817

INPUT

第一行两个数n,m
第二行n个数表示序列a
后面m行每行两个数l,r表示查询区间[l,r]

OUTPUT

对于每个查询输出答案

SAMPLE INPUT

5 5
64 2 18 9 100
1 5
2 4
2 3
1 4
3 4

SAMPLE OUTPUT

165
15
9
45
10

HINT

n , m <= 100000 , a[i] <= 1000000

SOLUTION

“玲珑杯”ACM比赛 Round #20

思路:显然ans利用约数和定理求,约数和定理链接

  sqrt(a[i])=1000,

  对于小于1000的素数,利用前缀和,复杂度m*168(素数总个数);

  对于大于1000的素数,一个数最多有一个这样的素数,利用莫队算法,求区间每个数的个数+1的乘积,莫队裸题;复杂度O(m*sqrt(n));

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
#define LL long long
const int N=1e5+100,M=1e6+10,inf=1e9+10;
const LL INF=1e18+10,mod=19260817;

int inv[M],mp[M];

void inverse(int n, int p) {
    inv[1] = 1;
    for (int i=2; i<=n; ++i) {
        inv[i] = (LL) (p - p / i) * inv[p%i] % p;
    }
}
int pos[N],a[N];
LL out,ans[N];
struct is
{
    int l,r,now;
    bool operator < (const is &a)const
    {
        if(pos[l]!=pos[a.l])
            return pos[l]<pos[a.l];
        return r<a.r;
    }
} s[N];
void add(int x)
{
    if(a[x]==1)return;
    out*=inv[mp[a[x]]+1];
    out%=mod;
    mp[a[x]]++;
    out*=mp[a[x]]+1;
    out%=mod;
}

void del(int x)
{
    if(a[x]==1)return;
    out*=inv[mp[a[x]]+1];
    out%=mod;
    mp[a[x]]--;
    out*=mp[a[x]]+1;
    out%=mod;
}

int ssp[N][200],sum[N][200];

vector<int>pr;
int vis[N];
void init()
{
    for(int i=2;i<=1000;i++)
    {
        if(!vis[i])pr.push_back(i);
        for(int j=i+i;j<=1000;j+=i)
            vis[j]=1;
    }
}
int main()
{
    inverse(1000000,19260817);
    init();
    //cout<<pr.size()<<endl;
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        memset(mp,0,sizeof(mp));
        out=1;
        int k=sqrt(n);
        for(int i=1;i<=n;i++)
        {
            pos[i]=(i-1)/k+1;
            scanf("%d",&a[i]);
            int temp=a[i];
            for(int j=0;j<pr.size();j++)
            {
                if(temp%pr[j]==0)
                {
                    while(temp%pr[j]==0)
                    {
                        temp/=pr[j];
                        ssp[i][j]++;
                    }
                }
            }
            for(int j=0;j<pr.size();j++)
                sum[i][j]=sum[i-1][j]+ssp[i][j];
            a[i]=temp;
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&s[i].l,&s[i].r);
            s[i].now=i;
        }
        sort(s+1,s+1+m);
        int L=1,R=0;
        for(int i=1; i<=m; i++)
        {
            while(R>s[i].r)
            {
                del(R);
                R--;
            }
            while(R<s[i].r)
            {
                R++;
                add(R);
            }
            while(L<s[i].l)
            {
                del(L);
                L++;
            }
            while(L>s[i].l)
            {
                L--;
                add(L);
            }
            LL q=1;
            for(int j=0;j<pr.size();j++)
            {
                q*=sum[s[i].r][j]-sum[s[i].l-1][j]+1;
                q%=mod;
            }
            ans[s[i].now]=(out*q)%mod;
        }
        for(int i=1;i<=m;i++)
            printf("%lld\n",ans[i]);
    }
    return 0;
}
时间: 2024-10-26 09:33:22

玲珑杯 1153 - 无影的神之右手 莫队的相关文章

(莫队算法)CodeForces - 617E XOR and Favorite Number

题意: 长度为n的数列,m次询问,还有一个k.每次询问询问询问从数列的L到R内有多少个连续子序列异或起来等于k. 分析: 因为事先知道这题可以用莫队写,就正好用这题练习莫队. 预处理每个前缀异或和. 然后莫队按分块排序后,不断更新,用一个数组cnt[]记录当前L到R前缀和的数量. R向右拉,新增的数量就是cnt[pre^k],pre表示当前这个R位置的前缀异或和,然后更新一下cnt. 其他的也类似. 算是一个比较好的入门题. 代码: 1 #include <cstdio> 2 #include

莫队算法

Beautiful Girl 题意 给定一个长度为 n 的序列 a[1], a[2], ..., a[n] . m 组询问 (l, r, K) , 求区间 [l, r] 去除重复的数之后的第 K 小. n, m <= 100000 . 分析 莫队算法 + 值域分块. 1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cctype> 5 #include &

BZOJ4241 历史研究 莫队算法 堆

欢迎访问~原文出处--博客园-zhouzhendong&AK 去博客园看该题解 题目 Description IOI国历史研究的第一人--JOI教授,最近获得了一份被认为是古代IOI国的住民写下的日记.JOI教授为了通过这份日记来研究古代IOI国的生活,开始着手调查日记中记载的事件. 日记中记录了连续N天发生的时间,大约每天发生一件. 事件有种类之分.第i天(1<=i<=N)发生的事件的种类用一个整数Xi表示,Xi越大,事件的规模就越大. JOI教授决定用如下的方法分析这些日记: 1.

CodeForces - 86D 莫队算法

http://codeforces.com/problemset/problem/86/D 莫队算法就是调整查询的顺序,然后暴力求解. 每回可以通过现有区间解ans(l,r)得到区间(l+1,r),(l-1,r),(l,r+1),(l,r-1)的区间解. 调整方式http://blog.csdn.net/bossup/article/details/39236275 这题比那个还要简单,查询的是K^2*Z,很清楚就是莫队算法,然而做的时候没有学过,回来补题补到 关键是我一直没明白为什么重载小于号

codeforces 617 E. XOR and Favorite Number(莫队算法)

题目链接:http://codeforces.com/problemset/problem/617/E 题目: 给你a1 a2 a3 ··· an 个数,m次询问:在[L, R] 里面又多少中 [l, r] 使得 al xor al+1 xor ··· ar 为 k. 题解: 本题只有区间查询没有区间修改,而且数据量不大(10w),所以可以用离线的方法解决. 使用莫队算法来解决,就需要O(1)的修改[L, R+1] .[L, R-1].[L+1, R].[L-1, R]. 详细的莫队可以百度学一

洛谷 P2056 采花 - 莫队算法

萧芸斓是 Z国的公主,平时的一大爱好是采花. 今天天气晴朗,阳光明媚,公主清晨便去了皇宫中新建的花园采花.花园足够大,容纳了 n 朵花,花有 c 种颜色(用整数 1-c 表示) ,且花是排成一排的,以便于公主采花. 公主每次采花后会统计采到的花的颜色数, 颜色数越多她会越高兴! 同时, 她有一癖好,她不允许最后自己采到的花中,某一颜色的花只有一朵.为此,公主每采一朵花,要么此前已采到此颜色的花,要么有相当正确的直觉告诉她,她必能再次采到此颜色的花. 由于时间关系,公主只能走过花园连续的一段进行采

hdu NPY and girls 莫队+逆元

NPY and girls Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description NPY's girlfriend blew him out!His honey doesn't love him any more!However, he has so many girlfriend candidates.Because there are to

洛谷 P3674 小清新人渣的本愿 [莫队 bitset]

传送门 题意: 给你一个序列a,长度为n,有Q次操作,每次询问一个区间是否可以选出两个数它们的差为x,或者询问一个区间是否可以选出两个数它们的和为x,或者询问一个区间是否可以选出两个数它们的乘积为x ,这三个操作分别为操作1,2,3 题面太强啦!!! 感觉就是莫队,想了一下分块不好搞更坚定了莫队的信念 $a-b=x$,$a=x+b$,放在权值数组上就是b右移x位,$bitset$大法好 加法同理 乘法,总共就$\sqrt{N}$个约数.... #include <iostream> #incl

(普通的)莫队算法简单介绍

莫队算法(由莫涛发明的)是一种离线的暴力算法(至少我这么认为).使用莫队算法的条件是,知道一个区间[l, r]的结果,那么也可以快速知道[l + 1, r],[l - 1, r], [l, r - 1], [l, r + 1]这四个区间的结果.于是可以想到,直接通过这样转移来解决一些问题.当然有些出题人机智,故意卡这种暴力,让你从头跑到尾然后从尾跑到头,于是时间复杂度高达O(n2) 而莫队算法就是通过改变处理询问的顺序来降低时间复杂度. 比如说现在知道一个区间[l1, r1],又要转移到[l2,