[dp][uestc]L - 피폴라치 디지털 업그레이드 버전
6759 단어 dp
데이터가 매우 커서 가방의 사고방식으로 수조를 열 수 없다.
먼저 피폴라 계수, 예를 들어fib(i)의 표현법을 순서대로 고려하고 i가 비교적 크다고 가정하면 피폴라 계수의 정의로fib(i)=fib(i-1)+fib(i-2)를 알 수 있다.다른 표현을 찾으려면 fib(i-1)나fib(i-2)를 계속 분할해야 한다. 만약에 분할fib(i-1)가fib(i)=2*fib(i-2)+fib(i-3)를 얻으면,이것은 서로 다른 성질을 보장할 수 없다(보충, 아마도 이 식을 중간 과정으로 삼아 모순항을 뜯어내어 유일성을 확보하는 것을 고려할 것이다. 그러나 하나의 모순을 없애면 반드시 새로운 모순이 생기기 때문에 안 된다. 구체적으로 말하면fib(i-2)=fib(i-3)+fib(i-4)를fib(i-2)의 모순을 없애고fib(i-3)의 모순이 생긴다. fib(i-3)는fib(i-1)에서 얻어서 유한한 분할을 통해 모순을 없앨 수 없다).따라서fib(i-2)를 뜯어보고 표현방식fib(i)=fib(i-1)+fib(i-3)+fib(i-4)를 얻는다.계속 나누면 앞과 유사하게fib(i-4)만 뜯을 수 있습니다.매번 최소fib수만 뜯을 수 있고 종점은fib(1) 또는fib(2)인 것을 발견하기 어렵지 않다.상기 과정에서 알 수 있듯이 1 또는 2+2*m=i, m는fib(i) 자체를 제외한 다른 표시 방법이고 상식에서 m=(i-1)/2(/모두 아래로 정돈하고 아래는 동일)을 나타낼 수 있다.ok, 우리는 n이 피폴라 계수인 상황을 성공적으로 해결했다.다음은 n이 피폴라 계수인 조합의 상황을 고려한다.n=fib(i)+fib(j), i>j를 가정하기;우리는fib(i)와fib(j)의 단독 상황을 알고 있다. 현재 조합하면 방금 분리된 사상을 참고할 수 있다. 다른 것은 현재fib(i)와fib(j)가 모두 분리될 수 있다는 것이다.가령 fb(j)를 분해한다고 가정하면 (왜 작은 것을 분해해야 하는지 물어볼 수도 있다. 왜냐하면 fb(i)분해에서fib(j)분해와 충돌하는 상황이 있기 때문이다) (j-1)/2+1조를 얻을 수 있기 때문이다.현재fib(i)를 뜯는 것을 고려하면 처음과 같은 사상은 종점에 변화가 생겼을 뿐이다. 종점(독립성을 확보하기 위해fib(j)의 분할 상황을 고찰한 결과 (j-1)/2가지 분할에서fib(j-1)로 시작하는 것을 발견했다. 따라서 종점은fib(j) 또는fib(j+1)로 등식2*m1+j 또는(j+1)=i,m1=(i-j)/2,m1은fib(i) 자체를 제외한 다른 표현 방법이다.fib(j)로 시작하여fib(j) 자체, 종점은fib(j+1) 또는fib(j+2), m2=(i-j-1)/2, m2는fib(i) 자체를 제외한 다른 표현 방법이다.종합하면fib(i)를 포함하는 표시는 (j-1)/2+1종,fib(i)를 포함하지 않는 표시는 m1*(j-1)/2+m2가 있다.현재 n=fib(i)+fib(j)+fib(k), i>j>k로 확대된 상황fib(j)와fib(k)의 조합은 이미 알고 있으며, 두 조로 나뉘어fib(j)로 시작하는 것과fib(j-1)로 시작하는 것,fib(i)에 대한 분할은 이전 방법과 같다. 이로써 dp[i][0]의 정의를 내린다.fib(i-1)로 시작하는 모든 조합, dp[i][1]:fib(i)로 시작하는 모든 조합이다.그래서 상태 이동 방정식 dp[i][1]=dp[j][0]+dp[j][1], dp[i][0]=(i-j-1)/2*dp[j][1]+(i-j)/2*dp[j][0]가 있고 최종 결과는 dp[maxi][0]+dp[maxi][1]이다.
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
long long int dp[88][2];//dp[i][0] comb[0~i] fib[i-1] [1] fib[i]
long long int fib[88];
void get_fibs()
{
fib[0]=1;fib[1]=1;
for(int i=2;i<88;i++)
fib[i]=fib[i-1]+fib[i-2];
}
vector<int> comb;// n fib
long long int n;
void solve()
{
comb.clear();
for(int i=87;i>0&&n;i--)
if(n>=fib[i])
{
n-=fib[i];
comb.push_back(i-1);
}
sort(comb.begin(),comb.end());
dp[0][1]=1;
dp[0][0]=comb[0]/2;
for(int i=1;i<comb.size();i++)
{
dp[i][1]=dp[i-1][0]+dp[i-1][1];
dp[i][0]=(comb[i]-comb[i-1]-1)/2*dp[i-1][1]+(comb[i]-comb[i-1])/2*dp[i-1][0];
}
printf("%lld
",dp[comb.size()-1][1]+dp[comb.size()-1][0]);
}
int main()
{
get_fibs();
int T;
scanf("%d",&T);
while(T--)
{
scanf("%lld",&n);
solve();
}
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
【경쟁 프로 전형적인 90문】008의 해설(python)
의 해설 기사입니다.
해설의 이미지를 봐도 모르는 (이해력이 부족한) 것이 많이 있었으므로, 나중에 다시 풀었을 때에 확인할 수 있도록 정리했습니다.
※순차적으로, 모든 문제의 해설 기사를 들어갈 예정입니다.
문자열...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
long long int dp[88][2];//dp[i][0] comb[0~i] fib[i-1] [1] fib[i]
long long int fib[88];
void get_fibs()
{
fib[0]=1;fib[1]=1;
for(int i=2;i<88;i++)
fib[i]=fib[i-1]+fib[i-2];
}
vector<int> comb;// n fib
long long int n;
void solve()
{
comb.clear();
for(int i=87;i>0&&n;i--)
if(n>=fib[i])
{
n-=fib[i];
comb.push_back(i-1);
}
sort(comb.begin(),comb.end());
dp[0][1]=1;
dp[0][0]=comb[0]/2;
for(int i=1;i<comb.size();i++)
{
dp[i][1]=dp[i-1][0]+dp[i-1][1];
dp[i][0]=(comb[i]-comb[i-1]-1)/2*dp[i-1][1]+(comb[i]-comb[i-1])/2*dp[i-1][0];
}
printf("%lld
",dp[comb.size()-1][1]+dp[comb.size()-1][0]);
}
int main()
{
get_fibs();
int T;
scanf("%d",&T);
while(T--)
{
scanf("%lld",&n);
solve();
}
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
【경쟁 프로 전형적인 90문】008의 해설(python)의 해설 기사입니다. 해설의 이미지를 봐도 모르는 (이해력이 부족한) 것이 많이 있었으므로, 나중에 다시 풀었을 때에 확인할 수 있도록 정리했습니다. ※순차적으로, 모든 문제의 해설 기사를 들어갈 예정입니다. 문자열...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.