虽说是一道裸题,但还是让小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. 学号:201621123032 《Java程序设计》第4周学习总结

    1:本周学习总结 1. 写出你认为本周学习中比较重要的知识点关键词 继承,多态,父类object,抽象类 2. 尝试使用思维导图将这些关键词组织起来 2:书面作业 2.1: 面向对象设计 1. 讲故事 ...

  2. 详谈C++虚函数表那回事(一般继承关系)

    沿途总是会出现关于C++虚函数表的问题,今天做一总结: 1.什么是虚函数表: 虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的.简称为V-Table. ...

  3. 利用python实现简单登陆注册系统

    #!/usr/bin/env python # -*- coding:utf-8 -*- def login(username,password): ''' :param username:用户名 : ...

  4. bzoj千题计划165:bzoj5127: 数据校验

    http://www.lydsy.com/JudgeOnline/upload/201712/prob12.pdf 区间的任意一个子区间都满足值域连续 等价于 区间任意一个长为2的子区间都满足值域连续 ...

  5. 从PRISM开始学WPF(二)Prism?

    目录: 从PRISM开始学WPF(一)WPF? 从PRISM开始学WPF(二)Prism? 从PRISM开始学WPF(三)Prism-Region? 从PRISM开始学WPF(四)Prism-Modu ...

  6. Binary Tree Xorder Traversal

     * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeN ...

  7. python全栈开发-logging模块(日记专用)

    一.概述 很多程序都有记录日志的需求,并且日志中包含的信息即有正常的程序访问日志,还可能有错误.警告等信息输出,python的logging模块提供了标准的日志接口,你可以通过它存储各种格式的日志,l ...

  8. linux下的Shell编程(7)使用-x和-n调试shell程序

    我们也可以在Shell下调试Shell Script脚本,当然最简单的方法就是用echo输出查看变量取值了.Bash也提供了真正的调试方法,就是执行脚本的时候用-x参数. sh -x filename ...

  9. Mego开发文档 - 从EF6/EFCore迁移到Mego

    从EF6/EFCore迁移到Mego框架 如果您有EntityFragmework6或EntityFragmeworkCore的开发经验,在首次接触Mego框架时会发现这两个框架非常相似,本文将帮忙您 ...

  10. mysql(1)—— 详解一条sql语句的执行过程

    SQL是一套标准,全称结构化查询语言,是用来完成和数据库之间的通信的编程语言,SQL语言是脚本语言,直接运行在数据库上.同时,SQL语句与数据在数据库上的存储方式无关,只是不同的数据库对于同一条SQL ...