- 费马小定理:
若 p p p 为素数 且 a , p a,p a,p 互素 ,则 a p − 1 ≡ 1 ( m o d p ) a^{p-1} \equiv 1 \pmod p ap−1≡1(modp) - 欧拉定理:
欧拉函数 φ ( m ) \varphi (m) φ(m) 表示 1 1 1 到 m m m 中与 m m m 互素的个数
若 a , m a,m a,m 互素,则 a φ ( m ) ≡ 1 ( m o d m ) a^{\varphi(m)} \equiv 1\pmod m aφ(m)≡1(modm)
遇到计算
1
2
(
m
o
d
10007
)
\frac{1}{2} \pmod {10007}
21(mod10007) 等价于
1
∗
(
2
的逆元
)
1*{(2的逆元)}
1∗(2的逆元)
计算时乘以
5004
5004
5004 就相当于乘以
1
2
\frac{1}{2}
21
#include<bits/stdc++.h>
using namespace std;
const int mod=10007;
const int MAXN=2005;
int f[MAXN][MAXN];
bool mem[MAXN][MAXN];
int q(int n,int a,int b)
{
if(mem[a][b]) return f[a][b];
mem[a][b]=1;
if(n==1)
{
if(a==0) return 0;
if(b==0) return 1;
return f[a][b]=5004;
}
else
{
if(a==0) return 0;
if(b==0) return 1;
return f[a][b]= ( 5004*q(n-1,a-1,b)%mod + 5004*q(n-1,a,b-1)%mod ) %mod;
}
}
int n,a,b;
int main()
{
cin>>n>>a>>b;
cout<<q(n,a,b)%mod;
return 0;
}
首先,根据题意可推出以下方程:
a
+
c
x
≡
b
(
m
o
d
2
k
)
a+cx\equiv b\space \pmod {2^k}
a+cx≡b (mod2k) , 若
x
x
x 有解则循环次数有限,无解则无限
等价于
c
x
≡
b
−
a
(
m
o
d
2
k
)
cx\equiv b-a\pmod{2^k}
cx≡b−a(mod2k)
最后使用快速幂即可
#include<bits/stdc++.h>
#define int long long
using namespace std;
int a,b,c,k,mod;
int get_pow(int x,int p)
{
int res=1,base=x;
while(p>0)
{
if(p & 1) res=(res*base)%mod;
base=base*base%mod;
p>>=1;
}
return res;
}
void print(int x)
{
while(x<0)
x+=mod;
cout<<x%mod;
}
signed main()
{
cin>>a>>b>>c>>k;
mod=1LL<<k;
int p = (1<<(k-1)) - 1; int t = b-a;
if(c%2!=0)
print( (t*get_pow(c,p))%mod );
else
{
while(c%2==0)
{
if(t%2==0) c/=2, t/=2, mod/=2;
else {puts("Inf"); return 0;}
}
int p = (mod>>1) - 1;
print( (t*get_pow(c,p))%mod );
}
return 0;
}
朴素的解法是枚举每一位的字母,时间复杂度为
O
(
2
6
n
)
O(26^n)
O(26n),此题最高为
2
6
10
26^{10}
2610
考虑折半搜索,复杂度降为 2 6 5 + 2 6 5 < < 2 6 10 26^5+26^5<<26^{10} 265+265<<2610
#include<bits/stdc++.h>
#define int long long
using namespace std;
int m,n,t,mod,inv;
int get_pow(int a,int b)
{
int base=a, res=1;
while(b>0)
{
if(b&1) res*=base, res%=mod;
base*=base, base%=mod;
b>>=1;
}
return res;
}
int cnt[1<<25];
void f1(int x,int s)
{
if(x==n/2) {cnt[s]++; return ;}
for(int i=1;i<=26;i++)
f1(x+1,((33*s)^i)%mod);
}
int f2(int x,int target)
{
if(x==n/2) return cnt[target];
int res=0;
for(int i=1;i<=26;i++)
{
int new_target=( (target^i)*inv ) % mod;
res+=f2(x-1,new_target);
}
return res;
}
signed main()
{
cin>>m>>t>>n; mod=(1<<m);
inv=get_pow(33,(1<<(m-1))-1);
f1(0,0);
cout<<f2(n,t);
return 0;
}