Codeforces 514E Darth Vader and Tree DP + 매트릭스 신속 멱
n과 x를 주고 (n<=10^5, x<=10^9)는 현재 완전한 n포크 나무가 있음을 나타낸다. 뿌리 노드가 시작점인 다음에 n개의 di를 주어 각각 대응하는 지점의 거리를 표시한다. (1<=di<=100) 그리고 모든 점에 대해 뿌리 노드까지의 거리가 x의 노드를 초과하지 않는 개수를 구한다. 숫자가 매우 클 수 있기 때문에 마지막 결과 모델에 10^9+7을 출력한다.
대략적인 사고방식:
아이디어가 코드 주석에 쓰여 있다
코드는 다음과 같습니다.
Result : Accepted Memory : 852 KB Time : 1045 ms
/*
* Author: Gatevin
* Created Time: 2015/2/25 11:49:15
* File Name: poi~.cpp
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
typedef long long lint;
/*
* di <= 100 , ti n i , t[1~100],
* dp[i] i ,
* dp[x] = dp[x - 1]*t[1] + dp[x - 2]*t[2] + ... + dp[x - 100]*t[100]
* , dp[0~99]
* S[x] = dp[0] + dp[1] + ... + dp[x]
* ,
* {dp[x], dp[x - 1], ... , dp[x - 99], S[x]} * | t[1] 1 0 ... 0 t[1] |
* | t[2] 0 1 ... 0 t[2] |
* |............... 1 t[3] |
* | t[100] 0 0 ... 0 t[100]|
* | 0 0 0 ... 0 1 |
* = {dp[x + 1], dp[x], dp[x - 1], ... dp[x - 98], S[x + 1]}
* , , dp
*/
const lint mod = 1000000007LL;
int n, x, t[110];
struct Matrix
{
lint a[110][110];
Matrix()
{
memset(a, 0, sizeof(a));
for(int i = 1; i <= 101; i++)
a[i][i] = 1;
}
};
Matrix operator + (Matrix m1, Matrix m2)
{
Matrix ret;
for(int i = 1; i <= 101; i++)
for(int j = 1; j <= 101; j++)
ret.a[i][j] = (m1.a[i][j] + m2.a[i][j]) % mod;
return ret;
}
Matrix operator * (Matrix m1, Matrix m2)
{
Matrix ret;
for(int i = 1; i <= 101; i++)
for(int j = 1; j <= 101; j++)
{
ret.a[i][j] = 0;
for(int k = 1; k <= 101; k++)
ret.a[i][j] = (ret.a[i][j] + m1.a[i][k]*m2.a[k][j] % mod) % mod;
}
return ret;
}
Matrix quick_pow(Matrix base, int pow)
{
Matrix I;
while(pow)
{
if(pow & 1)
I = I*base;
base = base*base;
pow >>= 1;
}
return I;
}
lint dp[110];
int main()
{
scanf("%d %d", &n, &x);
int tt;
memset(t, 0, sizeof(t));
for(int i = 1; i <= n; i++)
{
scanf("%d", &tt);
t[tt]++;
}
Matrix A;
memset(A.a, 0, sizeof(A.a));
for(int i = 1; i <= 100; i++)
A.a[i][1] = A.a[i][101] = t[i];
for(int i = 1; i < 100; i++)
A.a[i][i + 1] = 1;
A.a[101][101] = 1;
memset(dp, 0, sizeof(dp));
dp[0] = 1;
for(int i = 1; i <= 100; i++)
for(int j = 1; i - j >= 0 && j <= 100; j++)
dp[i] = (dp[i - j]*t[j] + dp[i]) % mod;
if(x <= 100)
{
lint ans = 0;
for(int i = 0; i <= x; i++) ans = (ans + dp[i]) % mod;
cout<<ans<<endl;
return 0;
}
A = quick_pow(A, x - 99);
lint S = 0;
for(int i = 0; i <= 99; i++) S = (S + dp[i]) % mod;
lint ans = 0;
for(int i = 1; i <= 100; i++)
ans = (ans + dp[100 - i]*A.a[i][101]) % mod;
ans = (ans + S*A.a[101][101]) % mod;
cout<<ans<<endl;
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Lowest Common Ancestor (LCA)Tree에서 두 nodes u와 v의 LCA는, root로부터 가장 멀리(deepest) 있는 공통 조상이다. Naive 하게 root에서 각 node까지의 경로를 비교하여 풀 수 있다. 두 배열을 비교하여 얻은 공...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.