Hatena::Grouptopcoder

skyaozoraの日記

 | 

2019-09-16

ARC100F,ColorfulSeaquences(1100)

15:53

問題

「Aに同じ数が含まれている」「Aの数が全てバラバラ」という2つの場合があるのですが、それぞれそうじゃない方だと解けない解法を使って解くというのが面白いなと。正解者数的に1100点の割にはかなり難しそう。

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define pf push_front
typedef long long lint;
typedef complex<double> P;
#define mp make_pair
#define fi first
#define se second
typedef pair<int,int> pint;
#define All(s) s.begin(),s.end()
#define rAll(s) s.rbegin(),s.rend()
#define REP(i,a,b) for(int i=a;i<b;i++)
#define rep(i,n) REP(i,0,n)
lint dp[25010][420];
lint d3[25010][420][2];
int a[420];
lint zyo[25010],kai[420],ika[420];
lint mo=1000000007;
map<int,int> me;
lint extgcd(lint a, lint b, lint &x, lint &y) {
  lint g = a; x = 1; y = 0;
  if (b != 0) g = extgcd(b, a % b, y, x), y -= (a / b) * x;
  return g;
}
lint invMod(lint a, lint m) {
  lint x, y;
  if (extgcd(a, m, x, y) == 1) return (x + m) % m;return 0;
}
int cal(void)
{
	int n,K,m,x=0,y=0;lint out=0;
	cin>>n>>K>>m;
	zyo[0]=1;rep(i,n+10) zyo[i+1]=(zyo[i]*K)%mo;
	kai[0]=1;rep(i,410) kai[i+1]=(kai[i]*(i+1))%mo;
	rep(i,410) ika[i]=invMod(kai[i],mo);
	
	rep(i,m) cin>>a[i];
	rep(i,m-K+1){
		int f=0;me.clear();
		rep(j,K){
			if(me[a[i+j]]>0) f=1;me[a[i+j]]++;
		}
		if(f<1){
			return zyo[n-m]*(n-m+1)%mo;
		}
	}
	me.clear();
	while(x<m){
		if(me[a[x]]>0) break;
		me[a[x]]++;x++;
	}
	me.clear();
	while(y<m){
		if(me[a[m-1-y]]>0) break;
		me[a[m-1-y]]++;y++;
	}
	
	memset(dp,0,sizeof(dp));
	memset(d3,0,sizeof(d3));
	rep(i,n) REP(j,1,K){
		dp[i+1][j]+=dp[i+1][j-1];
		if(j==K-1) dp[i+1][j]+=zyo[i];
		else dp[i+1][j]+=(dp[i][j+1]-dp[i][j])*(K-j);
		dp[i+1][j]%=mo;
		dp[i+1][j]+=dp[i][j];
		dp[i+1][j]%=mo;
	}
	if(x>=m && y>=m){
		d3[0][0][0]=1;
		rep(i,n+1) rep(j,K+1) rep(l,2){
			if(j>0 && i>0){
				d3[i][j][l]+=d3[i][j-1][l];
			}
			d3[i][j][l]%=mo;d3[i][j][l]+=mo;d3[i][j][l]%=mo;
			d3[i+1][1][l]+=d3[i][j][l];
			d3[i+1][j+1][l]+=mo-d3[i][j][l];
			if(j<K-1){
				d3[i+1][j+1][l]+=d3[i][j][l]*(K-j);
				d3[i+1][j+2][l]-=d3[i][j][l]*(K-j);
			}
			else if(j==K-1){
				d3[i+1][j+1][1]+=d3[i][j][l];
				d3[i+1][j+2][1]-=d3[i][j][l];
			}
		}
		rep(i,n){
			REP(j,m,K+1){
				//既にできてるやつ
				out+=d3[i][j][1]*zyo[n-i];
				out%=mo;
				//これから足すやつ。
				out+=d3[i][j][0]*(dp[n-i][j]-dp[n-i][j-1]);
				out%=mo;
			}
		}
		REP(j,m,K+1){
			out+=d3[n][j][1];out%=mo;
		}
		out*=kai[K-m];out%=mo;out*=ika[K];out%=mo;out+=mo;out%=mo;
		return out;
	}
	out=zyo[n-m]*(n-m+1)%mo;
	rep(i,n-m+1){
		out-=(zyo[i]-dp[i][x]+dp[i][x-1])*(zyo[n-m-i]-dp[n-m-i][y]+dp[n-m-i][y-1]);
		out%=mo;
	}
	out+=mo;out%=mo;
	return out;
}
int main()
{
	cout<<cal()<<endl;
}
 |