首页 > 其他分享 >【bzoj4869】【六省联考2017】相逢是问候(扩展欧拉函数)

【bzoj4869】【六省联考2017】相逢是问候(扩展欧拉函数)

时间:2022-10-28 20:02:32浏览次数:60  
标签:六省 bzoj4869 cntp varphi int numc return now 联考

和《花神游历各国》有异曲同工之妙。

首先能想到扩展欧拉定理:

\[a^b\equiv \begin{cases} a^{b\bmod \varphi(p)+\varphi(p)}&\text{if }b\geq\varphi(p)\\ a^b&\text{if }b< \varphi(p) \end{cases} \pmod p \]

观察到一个数经过若干次操作后肯定是 \(c^{c^{\cdots^{a_i}}}\) 的形态,所以我们肯定是不断递归取对这个数取模。

结论:如果对一个数 \(p\) 不断取 \(\varphi\),那么最多取到 \(O(\log p)\) 次这个数就会变成 \(1\)。

证明:

  • 若 \(p\) 为偶数,那么 \(\leq p\) 的数中,和 \(p\) 互质的数肯定只会是奇数,故 \(\varphi(p)\leq \dfrac{p}{2}\)。
  • 若 \(p\) 为奇数,那么一次取 \(\varphi\) 后 \(p\) 就会变成偶数,转回第一种情况。

所以对一个数 \(p\) 不断取 \(\varphi\) 的次数是 \(\log p\) 级别的。

所以如果一个数 \(a_i\) 经过一定次数的操作,它 \(\bmod p\) 的值就会不变。

准确地说,如果 \(p\) 取 \(cntp\) 次 \(\varphi\) 就能变成 \(1\),那么 \(a_i\) 经过 \(cntp\) 次操作后再操作都一直是一个定值。

所以每个数的前 \(cntp\) 次操作我们暴力算即可,这个过程中我们需要实现求 \(c^x\bmod p\)。

我们可以类似分块一样,设置一个值 \(B=\sqrt{p}\),并预处理出 \(c^{0},c^1,\cdots,c^{B}\) 模 \(p\) 的值,以及 \(c^{B},c^{2B},\cdots,c^{B\times B}\) 模 \(p\) 的值,这样就可以实现 \(O(1)\) 求 \(c^x\bmod p\) 了。

注意 \(a=0\) 需要特判,因为它要经过 \(cntp+1\) 次操作后才是一个定值。

注意暴力递归算 \(c^{c^{\cdots^{a_i}}}\) 的时候需要注意使用扩展欧拉定理时是按第一种情况还是按第二种情况。

代码如下:

#include<bits/stdc++.h>

#define LP 70
#define N 50010
#define ll long long

using namespace std;

namespace modular
{
	inline int add(int x,int y,int mod){return x+y>=mod?x+y-mod:x+y;}
	inline int dec(int x,int y,int mod){return x-y<0?x-y+mod:x-y;}
	inline int mul(int x,int y,int mod){return 1ll*x*y%mod;}
}using namespace modular;

inline int read()
{
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9')
	{
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
	{
		x=(x<<1)+(x<<3)+(ch^'0');
		ch=getchar();
	}
	return x*f;
}

int n,m,P,c,a[N];
int cntp,p[LP];
const int B=10000;
int pow1[LP][10010],pow2[LP][20010];
bool f1[LP][10010],f2[LP][20010];
//pow1[i]:c^i mod P,pow2[i]:c^(Bi) mod P
int minn[N<<2],sum[N<<2];

inline int getphi(int n)
{
	int ans=n;
	for(int i=2,t=sqrt(n);i<=t;i++)
	{
		if(!(n%i))
		{
			ans=ans/i*(i-1);
			while(!(n%i)) n/=i;
		}
	}
	if(n!=1) ans=ans/n*(n-1);
	return ans;
}

void init()
{
	p[0]=P;
	while(P!=1) p[++cntp]=P=getphi(P);
	P=p[0];
	for(int i=0;i<cntp;i++)
	{
		int np=p[i];
		pow1[i][0]=1;
		for(int j=1;j<=B;j++)
		{
			pow1[i][j]=mul(pow1[i][j-1],c,np);
			f1[i][j]=(f1[i][j-1]||(1ll*pow1[i][j-1]*c>=np));
		}
		pow2[i][0]=1;
		for(int j=1;j*B<=(np<<1);j++)
		{
			pow2[i][j]=mul(pow2[i][j-1],pow1[i][B],np);
			f2[i][j]=(f2[i][j-1]||f1[i][B]||(1ll*pow2[i][j-1]*pow1[i][B]>=np));
		}
	}
}

bool flag;

inline int poww(int x,int id)
{
//	assert(x<=(p[id]<<1));
	ll tmp=1ll*pow1[id][x%B]*pow2[id][x/B];
	flag|=f1[id][x%B]|f2[id][x/B];
	flag|=(tmp>=p[id]);
	return tmp%p[id];
}

int calc(int a,int numc)
{
	flag=0;
	int now=a;
	if(numc==cntp+1)
	{
		now=114514;
		numc--;
	}
	if(now>=p[numc]) flag=1,now=now%p[numc];
	for(int i=numc-1;i>=0;i--)
	{
		if(flag) now+=p[i+1];
		flag=0;
		now=poww(now,i);
	}
	return now;
}

inline void up(int k)
{
	sum[k]=add(sum[k<<1],sum[k<<1|1],P);
	minn[k]=min(minn[k<<1],minn[k<<1|1]);
}

void build(int k,int l,int r)
{
	if(l==r)
	{
		sum[k]=a[l]=read();
		return;
	}
	int mid=(l+r)>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
	up(k);
}

void update(int k,int l,int r,int ql,int qr)
{
	if(minn[k]>cntp) return;
	if(l==r)
	{
		minn[k]++;
		sum[k]=calc(a[l],minn[k]);
		return;
	}
	int mid=(l+r)>>1;
	if(ql<=mid) update(k<<1,l,mid,ql,qr);
	if(qr>mid) update(k<<1|1,mid+1,r,ql,qr);
	up(k);
}

int query(int k,int l,int r,int ql,int qr)
{
	if(ql<=l&&r<=qr) return sum[k];
	int mid=(l+r)>>1,ans=0;
	if(ql<=mid) ans=add(ans,query(k<<1,l,mid,ql,qr),P);
	if(qr>mid) ans=add(ans,query(k<<1|1,mid+1,r,ql,qr),P);
	return ans;
}

int main()
{
	n=read(),m=read(),P=read(),c=read();
	init();
	build(1,1,n);
	while(m--)
	{
		int opt=read(),l=read(),r=read();
		if(!opt) update(1,1,n,l,r);
		else printf("%d\n",query(1,1,n,l,r));
	}
	return 0;
}
/*
1 6 4 2
0
0 1 1 
1 1 1
0 1 1
1 1 1
0 1 1
1 1 1
*/

标签:六省,bzoj4869,cntp,varphi,int,numc,return,now,联考
From: https://www.cnblogs.com/ez-lcw/p/16837306.html

相关文章

  • LG7521 [省选联考 2021 B 卷] 取模
    LG7521[省选联考2021B卷]取模给定\(n\)个正整数\(a_i\),请你再其中选出三个数\(i,j,k(i\neqj,i\neqk,i\neqk)\),使得\((a_i+a_j)\bmoda_k\)的值最大。复......
  • 10月联考试卷反思
    一、语文成绩:96.5二、数学成绩:78三、数学加试(武汉某模拟试题)成绩:85四、英语成绩:114.5五、物理原始成绩:73赋分:84六、化学原始成绩:54赋分:61七、地理原始成绩:5......
  • [联考]钻石教练
    给定\(n\),和一个\(k\)次多项式,对于每个\(m\len\),设\(\sigma\)为一个大小为\(m\)且拆出的所有循环大小都为\(3\)的倍数的置换,\(|sp(\sigma)|\)为它拆出的循环数......
  • P4384 [八省联考 2018] 制胡窜
    P4384[八省联考2018]制胡窜考虑先将问题转化为切断两个位置使得没有任何一段中包含\(t\)。则最终的答案为\(\dbinom{n}{2}-\text{ans}\)。计\(t\)按左端点排序后......
  • [挑战记录][省选联考 2022] 预处理器
    2022100220:30开始答题20:35先水\(20\)分21:30假了,重构2022100306:34\(60\)分19:45继续重构,学习了一些\(\operatorname{string}\)的科技20:18过了#inclu......
  • 22 暑期 CD 班联考 Day4 之降低力度
    WZY在线捐献瞳孔沙城之巅城市定向SUNZH在线学猫叫新知之神SSHWY在线送温暖......
  • 题解【P7515 [省选联考 2021 A 卷] 矩阵游戏】
    P7515[省选联考2021A卷]矩阵游戏解题报告。不一定更好的阅读体验。一年前我在省选赛场上折戟沉沙,一年后我从到下的地方再摔一跤。我成功了,我仍然是以前的那个......
  • 省选联考2022
    省选联考2022先挖个坑,以后再来补(upt2022.9.22:补了d1t2和d2t2。预处理器小模拟,开\(2\)个\(\text{map}\),一个记录定义的变换,一个记录在本次变换中是否已经经过。......
  • CSP-S模拟2(联考)
    差点又双叒叕模拟退役上来先\(\%T2\),然后感觉就差一点,最后搞出来就十点多了..然后心态一度爆炸,有点小摆烂,上厕所冷静一下觉得还有时间,能抢救一下然后开了\(T1\),没......
  • CSP-S模拟2(联考) 谜之阶乘 子集 混凝土粉末 排水系统
    rank4040多分?T1:暴力;T2:构造T2:构造出(1--n)的连续整数分成k组,每组的数加起来一样。(n<=1e6)只要能实现一种构造方案,使得3k个连续数字分k组可以达到(a+b+c)相同(或2k,很显然......