题解:P4925 [1007] Scarlet的字符串不可能这么可爱
Solution P4925
Idea
先考虑没有限制。

这里我们用一种颜色代表一种字符。
第三个字符应该填什么?显然不能是红或者是蓝。有剩余 种选择。

接下来第四个肯定不能填蓝或者绿,但是可以填红。
可能会有人问:如果填和前面相同的颜色不会出现更长的回文串吗?
不会。因为我们在上面已经保证了不会存在长度为 或 的回文串,所以更长的更不可能存在。
计算答案:第一个可以选 种颜色,第二个可以选 种,剩下 个都是 种,答案就是 。
如果加上了限制呢?可以这么理解:

假如第 个位置已经规定是红色,我们可以先往后填,填第 个位置,显然有 种方案,再往后填就不难发现等价于没有限制的情况。这一部分的答案数是 。
然后往前填。

不难发现,第 个位置填颜色的时候,因为第 个和第 个都已经填好了,所以它只有 种填法。第 个位置填颜色的时候,因为第 个和第 个都已经填好了,所以它也只有 种填法。以此类推,当第 个位置填色的时候,因为第 个和第 个都已经填好了,所以它只有 种填法。由乘法原理,这一部分的答案是 种。
两个答案相乘,得答案为 。
Code
#include<bits/stdc++.h>
#define int long long
using namespace std;
int l,k,s,mod;
long long ans;
long long qpow(long long a,long long b){
long long res=1;
while(b){
if(b&1)res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
int m,n;
signed main(){
scanf("%lld%lld%lld%lld",&k,&l,&mod,&s);
k%=mod;
m=((k-1)%mod+mod)%mod;
n=((k-2)%mod+mod)%mod;
if(s)printf("%lld",1ll*m*qpow(n,l-2)%mod);
else printf("%lld",1ll*(k*m%mod)*(qpow(n,l-2)%mod)%mod);
return 0;
}
Tip
- 题目输入是 个数,为什么只输入了 个?
我们发现各个字符之间是等价的,所以是第几种并没有必要知道, 也就可有可无了。
输入 个是评测的特性:如果实际程序输入数比给定输入数少,会优先选择靠前的输入。变式一下,如果 在 之前输入,便不能省略了。也就是虽然输入文件中给定了 ,但是我们没有选择要它。
- 为什么
#define int long long和signed main?
这道题不用这句话会获得 分。这句话的作用是把所有 int 型变量定义成 long long 型,防止爆 int。
但是这句话也有副作用。int main() 不能定义成 long long main()。并且有些时候程序会因此 MLE 或 WA 等。所以不到万不得已不要用这个。
- 为什么有
m=((k-1)%mod+mod)%mod;和n=((k-2)%mod+mod)%mod;?
C++ 中,负数取模是负数。如果这题 为 ,则 就是负数,会出错,所以把它单独拿出来。

浙公网安备 33010602011771号