ε=(´ο`*)))唉,又快学完初等数论了,我又心血来潮,再次写下一篇壮美的篇章。
一 夜 复 习 两 茫 茫 。 看 一 句 , 忘 三 行 。 路 遇 友 人 , 脸 色 皆 凄 凉 。 视 死 如 归 入 考 场 , 做 小 抄 , 占 座 忙 。 考 完 之 后 心 凉 凉 , 左 右 曰 , 今 必 亡 。 查 询 成 绩 , 众 人 皆 过 我 独 亡 。 再 顾 昔 时 左 右 人 , 这 一 群 , 装 逼 郎 。 — — — 题 记 一夜复习两茫茫。\\看一句,忘三行。\\路遇友人,脸色皆凄凉。\\视死如归入考场,做小抄,占座忙。\\ 考完之后心凉凉,左右曰,今必亡。\\查询成绩,众人皆过我独亡。\\再顾昔时左右人,这一群,装逼郎。\\———题记 一夜复习两茫茫。看一句,忘三行。路遇友人,脸色皆凄凉。视死如归入考场,做小抄,占座忙。考完之后心凉凉,左右曰,今必亡。查询成绩,众人皆过我独亡。再顾昔时左右人,这一群,装逼郎。———题记
进制
略带而过
十进制转二进制
(1)短除法
(2)贪心算法
二进制转十进制
N ( 十 进 制 ) = a n ∗ 2 n + a n − 1 ∗ 2 n − 1 + … … + a 1 ∗ 2 1 + a 0 ∗ 2 0 N(十进制)=a_n*2^n+a_{n-1}*2^{n-1}+……+a_1*2^1+a_0*2^0 N(十进制)=an∗2n+an−1∗2n−1+……+a1∗21+a0∗20
b进制转十进制
乘以基数并展开:
x
=
a
n
∗
b
n
+
a
n
−
1
∗
b
n
−
1
+
…
…
+
a
1
∗
b
1
+
a
0
∗
b
0
x=a_n*b^n+a_{n-1}*b^{n-1}+……+a_1*b^1+a_0*b^0
x=an∗bn+an−1∗bn−1+……+a1∗b1+a0∗b0
x
=
(
…
(
a
n
∗
b
+
a
n
−
1
)
∗
b
+
…
)
∗
b
+
a
0
x=(…(a_n*b+a_{n-1})*b+…)*b+a_0
x=(…(an∗b+an−1)∗b+…)∗b+a0
十进制转b进制
快速幂
快速幂,顾名思义,就是快速计算某个数的多少次幂,其时间复杂度为 Θ ( log 2 x ) \Theta(\log_2 x) Θ(log2x)。
预备知识:
原理:倍增思想
a
∗
a
=
a
2
a
2
2
=
a
4
a
4
2
=
a
8
a*a=a^2\\{a^2}^2=a^4\\{a^4}^2=a^8
a∗a=a2a22=a4a42=a8
【核心代码】
int pow(int a,int b,int p)//快速幂求a^b%p
{
int res=1;
for(;b;b>>=1)
{
if(b&1) res=(ll)res*a%p;
a=(ll)a*a%p;
}
return res;
}
例题1:越狱
【题目描述】
监狱有连续编号为
1..
n
1..n
1..n的
n
n
n个房间,每个房间关押一个犯人。有
m
m
m种宗教,每个犯人可能信仰其中一种。如果相邻房间的犯人信仰的宗教相同,就可能发生越狱。求有多少种状态可能发生越狱,结果模
100003
100003
100003取余。
1
≤
m
≤
1
0
8
,
1
≤
n
≤
1
0
12
。
1≤m≤10^8,1≤n≤10^{12}。
1≤m≤108,1≤n≤1012。
【解析】
发生越狱的情况下不太好分析,所以我们可以先算出总方案数再减去不发生越狱的情况。
显然,所有的方案数为
m
n
m^n
mn ,所有不发生越狱的方案数为
m
∗
(
m
−
1
)
(
n
−
1
)
m*(m-1)^{(n-1)}
m∗(m−1)(n−1) 。
所以,发生越狱的方案数为
m
n
−
m
∗
(
m
−
1
)
(
n
−
1
)
m^n-m*(m-1)^{(n-1)}
mn−m∗(m−1)(n−1) 。
用快速幂即可完成。
【代码展示】
#include<bits/stdc++.h>
#define ud using namespace std
#define ll long long
ud;
ll m,n;
inline long long read()
{
long long sum=0,flag=1;
char c;
for(;c<'0'||c>'9';c=getchar())if(c=='-') flag=-1;
for(;c>='0'&&c<='9';c=getchar())sum=(sum<<1)+(sum<<3)+c-'0';
return sum*flag;
}
ll pow(ll a,ll b)
{
ll tmp=1;
while(b!=0)
{
if(b%2==1)
{
tmp*=a;
tmp%=100003;
}
b=b/2;
a*=a;
a%=100003;
}
return tmp;
}
int main()
{
m=read();
n=read();
ll ans=m*1LL*(pow(m,n-1)-pow(m-1,n-1)+100003)%100003;
//多加一个100003起到保险作用
printf("%lld\n",ans);
return 0;
}
例题2:倒水
【题目描述】
一天,CC买了N个容量可以认为是无限大的瓶子,开始时每个瓶子里有1升水。接着~~CC发现瓶子实在太多了,于是他决定保留不超过K个瓶子。每次他选择两个当前含水量相同的瓶子,把一个瓶子的水全部倒进另一个里,然后把空瓶丢弃。(不能丢弃有水的瓶子) 显然在某些情况下CC无法达到目标,比如N=3,K=1。此时CC会重新买一些新的瓶子(新瓶子容量无限,开始时有1升水),以到达目标。 现在CC想知道,最少需要买多少新瓶子才能达到目标呢?
1
<
=
N
<
=
1
0
9
,
K
<
=
1000
1<=N<=10^9,K<=1000
1<=N<=109,K<=1000 。
【解析】
显然,由题意我们可以得到,保留瓶子的水容量一定为
2
n
(
n
∈
N
∗
)
2^n(n\in N^*)
2n(n∈N∗) ,那么题目就可以转化为求
N
N
N 的二进制形式中从高位到低位保留
K
K
K 位
1
1
1 ,所需要补充的最小差值。