http://www.lydsy.com/JudgeOnline/problem.php?id=4869

终于A了。。。参考了下dalao的代码。。。

拓展欧几里得定理,改了几次就不变了,但是用的时候要在快速幂里判是不是要用。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = ;
int n, m, cnt;
ll p, c;
ll phi[N], table[N];
namespace seg // n^x = n^(x % phi[x] + phi[x])
{
struct data {
ll ans, mn;
} tree[N << ];
inline ll getphi(ll x)
{
ll ret = x, lim = x;
for(ll i = ; i * i <= lim; ++i) if(x % i == )
{
ret = ret * (i - ) / i;
while(x % i == ) x /= i;
}
// printf("ret=%d\n", ret);
if(x > ) ret = ret * (x - ) / x;
return ret;
}
inline ll power(ll x, ll t, ll p, bool &flag)
{
bool big = false;
ll ret = ;
for(; t; t >>= )
{
if(t & )
{
ret = ret * x ;
flag |= big | (ret >= p);
ret %= p;
}
x = x * x; if(x >= p) big = true, x %= p;
}
return ret;
}
ll calc(ll x, int t)
{
if(x >= phi[t]) x = x % phi[t] + phi[t];
for(int i = t - ; i >= ; --i)
{
bool flag = false;
x = power(c, x, phi[i], flag);
if(flag) x += phi[i];
}
return x % phi[];
}
inline void build(int l, int r, int x)
{
if(l == r) {
tree[x].ans = table[l];
return;
}
int mid = (l + r) >> ;
build(l, mid, x << );
build(mid + , r, x << | );
tree[x].ans = (tree[x << ].ans
+ tree[x << | ].ans) % phi[];
}
inline void update(int l, int r, int x, int a, int b)
{ //如果这次的幂和上次一样就不变了
if(tree[x].mn >= cnt) return;
if(l > b || r < a) return;
if(l == r)
{
++tree[x].mn;
tree[x].ans = calc(table[l], tree[x].mn);
return;
}
int mid = (l + r) >> ;
update(l, mid, x << , a, b);
update(mid + , r, x << | , a, b);
tree[x].mn = min(tree[x << ].mn,
tree[x << | ].mn);
tree[x].ans = (tree[x << ].ans +
tree[x << | ].ans) % phi[];
}
inline ll query(int l, int r, int x, int a, int b)
{
if(l > b || r < a) return ;
if(l >= a && r <= b) return tree[x].ans % phi[];
int mid = (l + r) >> , ret = ;
ret = (ret + query(l, mid, x << , a, b)) % phi[];
ret = (ret + query(mid + , r, x << | , a, b)) % phi[];
return ret;
}
} using namespace seg;
int main()
{
scanf("%d%d%lld%lld", &n, &m, &p, &c);
phi[] = p;
ll P = p;
while(P != ) phi[++cnt] = P = getphi(P);
phi[++cnt] = ;
for(int i = ; i <= n; ++i) scanf("%lld", &table[i]);
build(, n, );
while(m--)
{
int opt, l, r; scanf("%d", &opt);
if(opt == )
{
scanf("%d%d", &l, &r);
update(, n, , l, r);
}
if(opt == )
{
scanf("%d%d", &l, &r);
printf("%lld\n", query(, n, , l, r));
}
}
return ;
}

最新文章

  1. Windows 10 安装双系统 CentOS 7
  2. CAS认证原理图
  3. mysql delete删除记录数据库空间不减少问题解决方法
  4. maven资源文件的相关配置
  5. xcode 真机调试 failed to get the task for process xxx
  6. Python的平凡之路(1)
  7. Mercurial使用简单介绍【转】
  8. 转载:.NET Web开发技术简单整理
  9. 必须掌握的Linux命令
  10. 随应潮流-基于ABP+Angulsrjs现代化应用软件开发框架(2)-abp说明
  11. ZooKeeper安装、部署
  12. 使用MVVM减少控制器代码实战(减少56%)
  13. 细谈昆明SEO市场
  14. URL, URI, URN三者区别
  15. JavaWeb 例子 JDBC+JSP登陆注册留言板
  16. 修改 iOS AppIcon
  17. ●洛谷P3168 [CQOI2015]任务查询系统
  18. Mysql相关存储函数,函数,游标
  19. PHP之ThinkPHP框架(数据库)
  20. 【CQOI2012】局部极小值

热门文章

  1. Data of Ch5 --Dual rotor
  2. python——进制间的转换
  3. npm 发包
  4. STM32F407 开发环境搭建 程序下载 个人笔记
  5. 看板娘 &amp; 二次元 &amp; live2d
  6. Bone Collector II(hdu 2639)
  7. 【ZJOI2018 Round2游记】
  8. MongoDB小结16 - find【查询条件$in】
  9. 用Visual Studio 2010 打开Visual Studio 2013 (C#专用)
  10. CF #367 DIV2 E