Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) F2. Wrong Answer on test 233 (Hard Version) dp 数学
F2. Wrong Answer on test 233 (Hard Version)
Your program fails again. This time it gets "Wrong answer on test 233"
.
This is the harder version of the problem. In this version, 1≤n≤2⋅105. You can hack this problem if you locked it. But you can hack the previous problem only if you locked both problems.
The problem is to finish n one-choice-questions. Each of the questions contains k options, and only one of them is correct. The answer to the i-th question is hi, and if your answer of the question i is hi, you earn 1 point, otherwise, you earn 0 points for this question. The values h1,h2,…,hn are known to you in this problem.
However, you have a mistake in your program. It moves the answer clockwise! Consider all the n answers are written in a circle. Due to the mistake in your program, they are shifted by one cyclically.
Formally, the mistake moves the answer for the question i to the question imodn+1. So it moves the answer for the question 1 to question 2, the answer for the question 2 to the question 3, ..., the answer for the question n to the question 1.
We call all the n answers together an answer suit. There are kn possible answer suits in total.
You're wondering, how many answer suits satisfy the following condition: after moving clockwise by 1, the total number of points of the new answer suit is strictly larger than the number of points of the old one. You need to find the answer modulo 998244353.
For example, if n=5, and your answer suit is a=[1,2,3,4,5], it will submitted as a′=[5,1,2,3,4] because of a mistake. If the correct answer suit is h=[5,2,2,3,4], the answer suit a earns 1 point and the answer suite a′ earns 4 points. Since 4>1, the answer suit a=[1,2,3,4,5] should be counted.
Input
The first line contains two integers n, k (1≤n≤2⋅105, 1≤k≤109) — the number of questions and the number of possible answers to each question.
The following line contains n integers h1,h2,…,hn, (1≤hi≤k) — answers to the questions.
Output
Output one integer: the number of answers suits satisfying the given condition, modulo 998244353.
Examples
input
3 3
1 3 1
output
9
input
5 5
1 1 4 2 2
output
1000
input
6 2
1 1 2 2 1 1
output
16
Note
For the first example, valid answer suits are [2,1,1],[2,1,2],[2,1,3],[3,1,1],[3,1,2],[3,1,3],[3,2,1],[3,2,2],[3,2,3].
题意
现在有n道题,每道题有k个答案,但是你现在犯傻了,把第一题的答案交到了第二题,第二题交到了第3题,第k题交到了第(k%n)+1题的位置上去。
现在想知道,有多少种填答案的方案,可以使得交换后的正确数量多于交换前的正确数量。
题解
数据范围小的话,dp[i][j]表示现在考虑到了第i题,交换后比交换前多得j分。
那么如果h[i]==h[i+1]的话,dp[i][j]=dp[i-1][j],因为无论如何填什么正确得个数都不会变。
其他情况 dp[i][j] = dp[i-1][j+1]+dp[i-1][j-1]+(k-2)dp[i-1][j],有一种情况是之前对了,转换后错了;之前错了,转换后对了;其他k-2种答案都保持不变。
hard version我们要反着做,假设我们知道最后转换后和转换前分数一样得方案数为ans的话,那么k^n-ans表示的是转换后得分发生改变的方案数。
又因为转换前分数高和转换后分数高的方案数是一样的,因为对称,所以最后答案一定是 (k^n-ans)/2
那么这个ans怎么做呢,假设现在h[i]!=h[i+1]的个数为num个,因为相同的话没有意义,因为填什么都无所谓
我们枚举+1的位置有多少个,C(num,i);同样的-1也得i个C(num-i,i),其他num-2i个位置有k-2种选择(k-2)(num-2i),剩下n-num个位置都有k个选择k(n-num)。
那么i个+1位置的方案数其实就是C(num,i)C(num-i,i)(k-2)(num-2i)k(n-num),最后用所有的方案数减去他再除以2就完事。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2005;
const int mod = 998244353;
int h[maxn];
long long dp[maxn][maxn*2],base=2003,k,n;
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
scanf("%d",&h[i]);
if(k==1){
cout<<"0"<<endl;
return 0;
}
dp[0][base]=1;
for(int i=1;i<=n;i++){
for(int j=base-2000;j<=base+2000;j++){
if(h[i]==h[i%n+1]){
dp[i][j]=dp[i-1][j]*k%mod;
}else{
dp[i][j]=(dp[i-1][j+1]+dp[i-1][j-1]+dp[i-1][j]*(k-2))%mod;
}
}
}
long long ans = 0;
for(int i=1;i<=n;i++){
ans=(ans+dp[n][base+i])%mod;
}
cout<<ans<<endl;
}
#include<bits/stdc++.h>
using namespace std;
const long long mod = 998244353;
const int maxn = 2e5+7;
int n,k,h[maxn];
long long powmod(long long a,long long b){
if(b==0)return 1;
return b%2==0?powmod(a*a%mod,b/2):powmod(a*a%mod,b/2)*a%mod;
}
long long fac[maxn],inv[maxn];
long long C(int a,int b){
if(b<0||b>n)return 0;
return (fac[a]*inv[b]%mod)*inv[a-b]%mod;
}
int main(){
fac[0]=inv[0]=1;
for(int i=1;i<maxn;i++){
fac[i]=i*fac[i-1]%mod;
inv[i]=powmod(i,mod-2)*inv[i-1]%mod;
}
cin>>n>>k;
if(k==1){
cout<<"0"<<endl;
return 0;
}
for(int i=0;i<n;i++)
cin>>h[i];
int num = 0;
h[n]=h[0];
for(int i=0;i<n;i++){
if(h[i]!=h[i+1])num++;
}
long long ans = 0;
for(int i=0;i*2<=num;i++){
long long tmp = C(num,i)*C(num-i,i)%mod*powmod(k-2,num-2*i)%mod*powmod(k,n-num);
ans=(ans+tmp)%mod;
}
cout<<((powmod(k,n)-ans+mod)*inv[2])%mod<<endl;
}
Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) F2. Wrong Answer on test 233 (Hard Version) dp 数学的更多相关文章
- Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3
A,有多个线段,求一条最短的线段长度,能过覆盖到所又线段,例如(2,4)和(5,6) 那么我们需要4 5连起来,长度为1,例如(2,10)(3,11),用(3,10) 思路:我们想一下如果题目说的是最 ...
- Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) E. Arson In Berland Forest 二分 前缀和
E. Arson In Berland Forest The Berland Forest can be represented as an infinite cell plane. Every ce ...
- Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) D2. Optimal Subsequences (Hard Version) 数据结构 贪心
D2. Optimal Subsequences (Hard Version) This is the harder version of the problem. In this version, ...
- Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) C. Messy 构造
C. Messy You are fed up with your messy room, so you decided to clean it up. Your room is a bracket ...
- Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) B. Box 贪心
B. Box Permutation p is a sequence of integers p=[p1,p2,-,pn], consisting of n distinct (unique) pos ...
- Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) A. Math Problem 水题
A. Math Problem Your math teacher gave you the following problem: There are n segments on the x-axis ...
- Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) C Messy
//因为可以反转n次 所以可以得到任何可以构成的序列 #include<iostream> #include<string> #include<vector> us ...
- Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) B Box
#include<bits/stdc++.h> using namespace std; ]; ]; int main() { int total; cin>>total; w ...
- Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) A Math Problem
//只要从所有区间右端点的最小值覆盖到所有区间左端点的最大值即可 #include<iostream> using namespace std ; int x,y; int n; int ...
随机推荐
- 有抱负的 DevOps 和 SRE 工程师必读好书清单 | 文末有福利!
原文地址:https://medium.com/faun/10-great-books-for-aspiring-devops-sre-engineers-76536c7c4909 原文作者:Ayme ...
- Linux平台达梦数据库V7单实例安装方式之图形方式
一 前言 我们在学习任何一个应用时,了解它的最初步骤通常是学会如何进行安装配置,后序才去关心如何使用,学习达梦数据库也是如此,而达梦数据库的安装提供了多种方式,接下来会一一介绍每种安装方式,达梦数据库 ...
- Redis内存数据库在Exchange会议室的整体应用架构
注:本文是别人写的,感觉写得很好就转过来,版权归原作者所有哦,谁知道出处可以告诉我,谢谢. 根据以上的会议室应用现状分析,该架构的核心是把历史发生的会议室申请数据定时同步到Redis内存数据库中,对于 ...
- Object::connect: No such slot xxx 解决方法
在所有代码和槽函数全部写好之后,进行编译时竟然报 No such slot xxxx,奇怪 Starting E:\01_project\03_C++\key\debug\key.exe... Obj ...
- 31(1).密度聚类---DBSCAN算法
密度聚类density-based clustering假设聚类结构能够通过样本分布的紧密程度确定. 密度聚类算法从样本的密度的角度来考察样本之间的可连接性,并基于可连接样本的不断扩张聚类簇,从而获得 ...
- 调试seanbell/intrinsic遇到的坑
那些遗忘过去的人注定要重蹈覆辙.——乔治•桑塔亚纳 Authorized error 刚开始按作者 GitHub 上的指示,当运行环境配置好,并且 make 之后,因为生成的 decompose.p ...
- Vue 小练习01
有红, 黄, 蓝三个按钮, 以及一个200X200px的矩形box, 点击不同的按钮, box的颜色会被切换为指定的颜色 <!DOCTYPE html> <html lang=&qu ...
- 聊聊 Java8 以后各个版本的新特性
作者:ZY5A59 juejin.im/post/5d5950806fb9a06b0a277412 某天在网上闲逛,突然看到有篇介绍 Java 11 新特性的文章,顿时心里一惊,毕竟我对于 Java ...
- linux中rpm和yum
一.rpm介绍 一种用于互联网下载包的打包及安装工具.它生成具有.RPM 扩展名的文件.RPM 是 RedHat Package Manager(RedHat 软件包管理工具)的缩写,类似 windo ...
- Go-数据类型以及变量,常量
一.数据类型 1.字符串类型 string 2.数字类型 有符号整型: int: int 在32位机器上是int32 在64位机器是int64 int8: int8 表示数字范围是 正负2的7次方减1 ...