[20200723NOIP提高組模擬T1]同餘
題目大意:
對於四個非負整數$n,c,p,m$以及長度為n的陣列${a_{i}}$請求出方程$\sum_{i=1}^{n} \prod_{j=1}^{a_{i}}x_{i,j} \equiv c (mod\ p)$在$x_{i,j}\in [0,p)$中整數解的個數mod $m$後的值.solution:
本題極其噁心,只給了$16MB$的空間,於是乎,看完題解後,我們推起了式子.
首先我們來分析一下$\prod_{i=1}^{n}x_{i} \equiv c(mod \ p)$的解的個數.分情況討論:
一、$c\neq 0$時,由於$x\in [0,p)$,該範圍內沒有p的倍數,所以對任意的$i$有$x_{i} \neq 0$,根據分步乘法原理,我們可以得$\prod_{i=1}^{n} x_{i} \not\equiv c(mod \ p)$
二、$c=0$時,我們可以利用正難則反原理,所有組合的個數為$p^{n}$,$\prod_{i=1}^{n} x_{i} \not\equiv c(mod \ p)$的解的個數為$(p-1)^{n}$,所以$\prod_{i=1}^{n} x_{i} \equiv 0(mod \ p)$的解個數為$b_{1}=p^{n}-(p-1)^{n}$.
我們分析完了$n=1$的情況,接下來分析$n>1$時狀態的轉移.
一、$c=0$時,$\prod_{i=1}^{n_{1}}x1_{i}+\prod_{j=1}^{n_{2}}x2_{j} \equiv 0(mod \ p)$成立時,有以下情況:
(1)$\prod_{i=1}^{n_{1}} x1_{i} \equiv 0(mod \ p)$且$\prod_{j=1}^{n_{2}} x2_{j} \equiv 0(mod \ p)$,此時據乘法原理將$b_{1} \cdot b_{2}$計入答案$b_{3}$;
(2)$\prod_{i=1}^{n_{1}} x1_{i} \equiv c_{1}(mod \ p)$,$\prod_{i=1}^{n_{2}} x2_{i} \equiv c_{2}(mod \ p)$且$c_{1}+c_{2}==p$,共有$p-1$種情況使$c_{1}+c_{2}==p$,根據乘法原理和加法原理,我們將$(p-1)\cdot a_{1} \cdot a_{2}$計入答案.
由此可得,$b_{3}=b_{1}\cdot b_{2} + (p-1) \cdot a_{1} \cdot a_{2}$
二、$c\neq 0$時,$\prod_{i=1}^{n_{1}}x1_{i}+\prod_{j=1}^{n_{2}}x2_{j} \equiv c(mod \ p)$成立,有以下情況:
(1)$\prod_{i=1}^{n_{1}}x1_{i} \equiv 0(mod \ p)$,那需滿足$\prod_{j=1}^{n_{2}}x2_{j} \equiv c(mod \ p)$,所以將$b_{1}\cdot a_{2}$計入答案$a_{3}$;
(2)$\prod_{j=1}^{n_{2}}x2_{j} \equiv 0(mod \ p)$,仿照上例顯然,將$b_{2} \cdot a_{1}$計入答案$a_{3}$;
(3)$\prod_{i=1}^{n_{1}}x1_{i} \equiv c_{1}(mod \ p)$,$\prod_{j=1}^{n_{2}}x2_{j} \equiv c_{2}(mod \ p)$ $(c_{1}\neq 0,c_{2}\neq 0)$,欲滿足條件,當且僅當$c_{1}+c_{2} \equiv c$,經過我們手玩發現,共有$p-2$種,所以根據分佈乘法原理,將$(p-2) \cdot a_{1} \cdot a_{2}$計入答案$a_{3}$;
由上可知,$a_{3}=b_{1} \cdot a_{2} + b_{2} \cdot a_{1} + (p-2) \cdot a_{1} \cdot a_{2}$.
此後,我們只需根據此二式一一遞推下去即可,記得取模防爆.
code:
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<queue> #define R register #define next exnttttttttt #define debug puts("mlg") using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; inline ll read(); inline void write(ll x); inline void writesp(ll x); inline void writeln(ll x); inline ll quick_pow(ll _,ll __,ll ___){ll ____=1;for(;__;__>>=1){if(__&1) ____*=_,____%=___;_*=_;_%=___;}return ____;} ll T; ll n,c,p,m; ll a; ll a1,a2,ansA,ansB,b1,b2; inline ll Mod(ll _){return (_%m+m)%m;} inline void mod(ll &_){_=Mod(_);return;} int main(){ freopen("congruence.in","r",stdin); freopen("congruence.out","w",stdout); T=read(); while(T--){ n=read();c=read();p=read();m=read(); a=read(); ansA=a2=a1=Mod(quick_pow(p-1,a-1,m)); ansB=b2=b1=Mod(quick_pow(p,a,m)-quick_pow(p-1,a,m)); --n; for(R ll i=1;i<=n;i++){ a=read(); a1=Mod(quick_pow(p-1,a-1,m)); b1=Mod(quick_pow(p,a,m)-quick_pow(p-1,a,m)); a2=ansA;b2=ansB; ansA=Mod(Mod(b1*a2)+Mod(b2*a1)+Mod(Mod((p-2)*a1)*a2)); ansB=Mod(Mod(b1*b2)+Mod(Mod((p-1)*a1)*a2)); } if(c==0) writeln(ansB); else writeln(ansA); } } inline ll read(){ll x=0,t=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') t=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*t;} inline void write(ll x){if(x<0){putchar('-');x=-x;}if(x<=9){putchar(x+'0');return;}write(x/10);putchar(x%10+'0');} inline void writesp(ll x){write(x);putchar(' ');} inline void writeln(ll x){write(x);putchar('\n');}