HDU 5794 A Simple Chess(허용 원리 + Lucas 정리 + dp)
A Simple Chess
문제 설명
n*m 바둑판이 있는데, 바둑알 한 개가 (1,1)칸에서 (n,m)칸으로 이동해야 한다.이 바둑알은 좌표 (x1, y1) 의 칸에서 칸 (x2, y2) 으로 뛰어넘을 수 있으며, 단지 다음과 같다.
(x2-x1)^2+(y2-y1)^2=5 x2>x1,y2>y1
바둑판에 r개의 칸이 있고 장애물이 있어서 바둑알은 장애물이 있는 칸에 떨어질 수 없다.이 바둑알이 기점에서 종점까지 모두 몇 가지 방안이 있는지 계산해 보세요.
입력 형식
몇 개의 그룹 데이터(<=25조)가 있는데 각 그룹의 데이터에 대해 형식은 다음과 같다. 한 줄, 세 개의 정수 n, m, r 다음 r줄, 한 줄에 두 개의 정수는 장애물이 있는 칸의 좌표를 나타낸다.
출력 형식
각 그룹의 데이터에 대해 한 줄, 한 정수를 출력하여 원하는 방안의 수를 나타낸다.mod 110119
샘플 입력 1
1 1 0 3 3 0 4 4 1 2 1 4 4 1 3 2 7 10 2 1 2 7 1
샘플 출력 1
1 0 2 1 5
샘플 입력 2
58939239 79926962 4 28255565 36535194 51497377 67322260 48931736 62290476 23383627 30097072
샘플 출력 2
9061
프롬프트
100% 데이터: 1≤n, m≤10^18, 0≤r≤100(1,1)칸에 장애가 없습니다.
편의를 위해 제목의 x, yx, y 좌표를 모두 1로 줄여 (0,0)(0,0)에서 (n-3-1, m-31)(n-3-1, m-3-1)로 변경한다.
만약 장애를 고려하지 않는다면 (0,0)(0,0)에서 (x,y)(x,y)(x,y)까지의 방안 수는 하나의 조합수이다. 이것은 비교적 잘 추측할 수 있다. 바로 C2x이다. 즉, y3x+y3 C+y 3 x-3 x-3 x-3이다. (x,y)(x,y)는 도달할 수 있고 x+y만 도달할 수 있다.
장애의 수가 비교적 적고 용납을 고려하여 F[i] F[i]로 하여금 (1,1)(1,1)에서 출발하여 지나는 첫 번째 장애는 ii의 장애이다. 그러면 ii의 왼쪽 아래에 있는 모든 장애물에 대해
F[i]=C2xi−yi3xi+yi3−∑jF[j]×C2tx−ty3tx+ty3,tx=xi−xj,ty=yi−yj F [ i ] = C x i + y i 3 2 x i − y i 3 − ∑ j F [ j ] × C t x + t y 3 2 t x − t y 3 , t x = x i − x j , t y = y i − y j
직접 기억화 검색을 하고 폭력적으로 그 점들을 왼쪽 아래에 열거하면 된다.
조합수
Lucas L u c a s 처리
이 가능하다, ~할 수 있다,...
0 0, 이 때도 가지 못한다는 것을 의미하기 때문에 되돌아가야 한다
0 0
또 종점이 장애라면 답도 주의해야 한다
0 0
총 시간 복잡도 O (n2×???) O ( n 2 × ? ? ? ) ,그래도 금방.
코드:
#include
#include
#include
#include
#define N 105
#define ll long long
using namespace std;
const ll mod=110119;
ll n,m,r,F[N],X[N],Y[N],fac[110220],inv[110220];
bool mark[N];
ll C(ll a,ll b)
{
if(areturn 0;
return fac[a]*inv[b]%mod*inv[a-b]%mod;
}
ll Lucas(ll a,ll b)
{
if(areturn 0;
if(a<0||b<0)return 0;
if(b==0||a==0)return 1;
return Lucas(a/mod,b/mod)*C(a%mod,b%mod)%mod;
}
ll DP(ll p)
{
ll i,j;
if(F[p]!=-1)return F[p];
if(mark[p])return F[p]=0;
F[p]=Lucas((X[p]+Y[p])/3,(2*Y[p]-X[p])/3);
for(i=1;i<=r;i++)
if(X[i]if(mark[i])continue;
F[p]-=DP(i)*Lucas((X[p]+Y[p]-X[i]-Y[i])/3,(2*(Y[p]-Y[i])-X[p]+X[i])/3)%mod;
F[p]%=mod;
}
F[p]+=mod;F[p]%=mod;
return F[p];
}
int main()
{
ll i,j,k,x,y;bool f;
fac[0]=fac[1]=inv[0]=inv[1]=1;
for(i=2;i<=mod;i++)
{
fac[i]=fac[i-1]*i%mod;
inv[i]=(mod-mod/i)*inv[mod%i]%mod;
}
for(i=2;i<=mod;i++)inv[i]=inv[i]*inv[i-1]%mod;
while(scanf("%lld%lld%lld",&n,&m,&r)!=EOF)
{
f=0;
for(i=1;i<=r;i++)
{
scanf("%lld%lld",&X[i],&Y[i]);
if(X[i]==n&&Y[i]==m)f=1;
}
if(f){puts("0");continue;}
for(i=1;i<=r;i++)X[i]--,Y[i]--;
X[++r]=n-1;Y[r]=m-1;
for(i=1;i<=r;i++)mark[i]=(X[i]+Y[i])%3!=0;
memset(F,-1,sizeof(F));
printf("%lld
",DP(r));
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
HDU 5794 A Simple Chess(허용 원리 + Lucas 정리 + dp)n*m 바둑판이 있는데, 바둑알 한 개가 (1,1)칸에서 (n,m)칸으로 이동해야 한다.이 바둑알은 좌표 (x1, y1) 의 칸에서 칸 (x2, y2) 으로 뛰어넘을 수 있으며, 단지 다음과 같다. (x2-x1)^2...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.