虽说是一道裸题,但还是让小C学到了一点姿势的。

Description

  给定一个长度为n的数组w,模数m和询问次数q,每次询问给定l,r,求:

    

  对m取模的值。

Input

  第一行两个整数n,m,表示数组长度和模数。
  接下来一行n个数,表示w数组。
  接下来一行一个整数q,表示询问次数。
  接下来q行,每行两个整数l,r,表示一次询问。

Output

  对于每次询问,输出一行一个整数表示答案。

Sample Input

  6 1000000000
  1 2 2 3 3 3
  8
  1 1
  1 6
  2 2
  2 3
  2 4
  4 4
  4 5
  4 6

Sample Output

  1
  1
  2
  4
  256
  3
  27
  597484987

HINT

  1 ≤ n ≤ 105,1 ≤ m ≤ 109,1 ≤ wi ≤ 109,1 ≤ q ≤ 105,1 ≤ l ≤ r ≤ n

Solution

  看到这么清奇的式子,你大概会第一时间想到降幂大法吧?

  先说说扩展欧拉定理,对于任意正整数a,b,p:

    

  所以假设堆叠的幂次足够大,那么式子就可以转化为:

      

  

  已知p经过至多2log次phi就会变成1。

  所以递归求解,至多走到2log层模数就会变成1,所以返回0就行。

  所以这道题就非常显然了,首先预处理出m的所有phi,对于每个询问,从l开始直接递归暴力,直到模数为1时返回。

  还有一个问题,在求a^b%p的时候,怎么比较b和phi(p)的大小呢?

  一种思路就是暴力计算a的后log项的值,注意还要特判1的情况,但这样写起来确实麻烦。

  当然,有一种非常精妙的取模写法:

int modulo(ll x,int mod) {return x<mod?x:x%mod+mod;}

  这是在做什么呢?这就是在比较b和phi(p)的大小,如果b<phi(p),返回b;否则返回b%phi(p)+phi(p)。

  然后原式就变成了这样:

    

  这样做看上去漏洞百出,可能的情况是,原本我们要计算,其中大等于

  然而我们计算,将取模后,却发现小于了。

  是否有这种可能呢?

  其实就相当于判断是否有可能成立,我们可以发现,当a>2时式子是不可能成立的。

  所以我们来看一看 是否有可能成立。

  有可能。

  当且仅当p=6时,不等式成立。

  然而6有什么特殊的性质呢?

  我们发现phi(x)=6只有三个解:x=7,x=9或x=18。

  所以接下来我们只要证明   和   即  和  在对x取模的意义下相等即可。(其中phi(x)=6)

  若a为x的倍数,显然它们对x取模都等于0,对于答案无影响。

  当x=7时,,所以 

  当x=9时,若 ,则影响同上;

        若 ,一定有,所以一定有 

               所以一定有 ,对于答案是没有影响的;

  当x=18时,若  或 ,则影响同上;

       我们有一个显然的结论:同余方程  的解为 

       若 ,则 ,则 ,则 

       若 ,则  且 ,则 ,则 

  所以综上,我们就证明了该算法的正确性。

  时间复杂度

#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
#define MN 100005
using namespace std;
int a[MN],mod[MN];
int n,p;
bool fg; inline int read()
{
int n=,f=; char c=getchar();
while (c<'' || c>'') {if(c=='-')f=-; c=getchar();}
while (c>='' && c<='') {n=n*+c-''; c=getchar();}
return n*f;
} inline int pro(ll x,int md) {return x<md?x:x%md+md;}
inline int mi(int x,int y,int md)
{
register int z=;
for (;y;x=pro(1LL*x*x,md),y>>=)
if (y&) z=pro(1LL*z*x,md);
return z;
} int dfs(int x,int y,int lim)
{
if (x==lim) return a[x]>=mod[y]?a[x]%mod[y]+mod[y]:a[x];
if (mod[y]==) return ;
return mi(a[x],dfs(x+,y+,lim),mod[y]);
} int main()
{
register int i,j,x,y;
n=read(); mod[]=read();
for (i=;mod[i]>;++i)
{
mod[i+]=x=mod[i];
for (j=;j*j<=x;++j)
{
for (fg=;x%j==;x/=j,fg=true);
if (fg) mod[i+]=1LL*mod[i+]*(j-)/j;
}
if (x>) mod[i+]=1LL*mod[i+]*(x-)/x;
}
for (i=;i<=n;++i) a[i]=read();
for (p=read();p;--p)
{
x=read(); y=read();
printf("%d\n",dfs(x,,y)%mod[]);
}
}

Last Word

  打Codeforces的时候正纳闷这种情况该怎么处理,却发现大佬们清一色都是这么写的。

  小C觉得自己的证明蠢得不行啊……

  如果读者有更直观的证明该算法的正确性的方法请务必告诉小C。

[Codeforces]906D Power Tower的更多相关文章

  1. CodeForces - 906D Power Tower(欧拉降幂定理)

    Power Tower CodeForces - 906D 题目大意:有N个数字,然后给你q个区间,要你求每一个区间中所有的数字从左到右依次垒起来的次方的幂对m取模之后的数字是多少. 用到一个新知识, ...

  2. Codeforces 906D Power Tower(欧拉函数 + 欧拉公式)

    题目链接  Power Tower 题意  给定一个序列,每次给定$l, r$ 求$w_{l}^{w_{l+1}^{w_{l+2}^{...^{w_{r}}}}}$  对m取模的值 根据这个公式 每次 ...

  3. Codeforces Round #454 (Div. 1) CodeForces 906D Power Tower (欧拉降幂)

    题目链接:http://codeforces.com/contest/906/problem/D 题目大意:给定n个整数w[1],w[2],……,w[n],和一个数m,然后有q个询问,每个询问给出一个 ...

  4. [CodeForces - 906D] Power Tower——扩展欧拉定理

    题意 给你 $n$ 个 $w_i$ 和一个数 $p$,$q$个询问,每次询问一个区间 $[l,r] $,求 $w_l ^{w_{l+1}^{{\vdots}^{w_r}}} \ \% p$ 分析 由扩 ...

  5. CodeForces 907F Power Tower(扩展欧拉定理)

    Priests of the Quetzalcoatl cult want to build a tower to represent a power of their god. Tower is u ...

  6. 【CodeForces】906 D. Power Tower 扩展欧拉定理

    [题目]D. Power Tower [题意]给定长度为n的正整数序列和模数m,q次询问区间[l,r]累乘幂%m的答案.n,q<=10^5,m,ai<=10^9. [算法]扩展欧拉定理 [ ...

  7. Codeforces Round #454 D. Power Tower (广义欧拉降幂)

    D. Power Tower time limit per test 4.5 seconds memory limit per test 256 megabytes input standard in ...

  8. CodeForces 906D (欧拉降幂)

    Power Tower •题意 求$w_{l}^{w_{l+1}^{w_{l+2}^{w_{l+3}^{w_{l+4}^{w_{l+5}^{...^{w_{r}}}}}}}}$ 对m取模的值 •思路 ...

  9. [CodeForces - 1225D]Power Products 【数论】 【分解质因数】

    [CodeForces - 1225D]Power Products [数论] [分解质因数] 标签:题解 codeforces题解 数论 题目描述 Time limit 2000 ms Memory ...

随机推荐

  1. QTableView

    QTableView常用于实现数据的表格显示.下面我们如何按步骤实现学生信息表格: 一 添加表头 //准备数据模型     QStandardItemModel *student_model = ne ...

  2. Codeforces 837E. Vasya's Function

    http://codeforces.com/problemset/problem/837/E   题意: f(a, 0) = 0; f(a, b) = 1 + f(a, b - gcd(a, b)) ...

  3. 02-移动端开发教程-CSS3新特性(中)

    1. 新的背景 背景在CSS3中也得到很大程度的增强,比如背景图片尺寸.背景裁切区域.背景定位参照点.多重背景等. 1.1 background-size设置背景图片的尺寸 cover会自动调整缩放比 ...

  4. JAVA_SE基础——45.基本类型变量.值交换[独家深入解析]

    需求:定义一个函数交换两个基本类型变量的值. 相信看过我前面的文章的同学都应该看的懂我以下的代码: class Demo2 { public static void main(String[] arg ...

  5. 帧动画的创建方式 - xml方式

    废话不多说,先看东西   创建帧动画1 - xml方式 帧动画的创建方式主要以下2种: * 用xml创建动画: * 用代码创建动画:   本文内容主要关注 xml文件 创建帧动画的方式   xml文件 ...

  6. Docker学习笔记 - Docker的数据卷容器

    一.什么是数据卷容器 如果你有一些持续更新的数据需要在容器之间共享,最好创建数据卷容器. 数据卷容器:用于容器间的数据共享,主动挂载宿主机目录,用于其他容器挂载和共享. 二.数据卷容器的操作 1.创建 ...

  7. iOS 封装.framework 以及使用

    .framework是什么? .framework是什么? 这个问题相信做iOS的都知道答案. 在我们的日常开发中,经常会用到各种已经封装好的库,比如支付宝.微信SDK等等中的库,这些库可以给我们的开 ...

  8. SublimeText用FileHeader给代码文件生成头部注释

    https://github.com/shiyanhui/FileHeader 修改的模板在这个路径下:C:\Users\[USERNAME]\AppData\Roaming\Sublime Text ...

  9. [Kaggle] dogs-vs-cats之制作数据集[1]

    Step 0:导入必要的库 import tensorflow as tfimport os Step 1:获取图片文件名以及对应的标签 首先是读取给定路径下所有图片的名称以及对应的标签.os.lis ...

  10. scrapy分布式的几个重点问题

    我们之前的爬虫都是在同一台机器运行的,叫做单机爬虫.scrapy的经典架构图也是描述的单机架构.那么分布式爬虫架构实际上就是:由一台主机维护所有的爬取队列,每台从机的sheduler共享该队列,协同存 ...