hdu3652 (디지털 DP)

문제의 의미 : 1-N (N <= 1,000,000,000) 번호를 찾고는 기술 (13)로 나눌 것이다. 숫자 13는 서브 문자열의 숫자를 포함한다


해결 방법 : 디지털 DP. LL의 DP는 [중고] 이제, 지금 예비 비트 [iflow [REM] 레코드 [있다] 13가되었는지 여부 앞의 표현이, iflow은 REM 아마도 필요가 나머지를 나타내고,가 감소하는지 여부를 DP 처리를 나타낸다.


코드 :

/******************************************************
* author:xiefubao
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <string.h>
//freopen ("in.txt" , "r" , stdin);
using namespace std;

#define eps 1e-8
const double pi=acos(-1.0);
typedef long long LL;
const int Max=10100;
const int INF=1000000007;
LL dp[20][20][2][2][15];
int reminder[20];
int num[30];
LL dfs(int pre,int now,bool have,bool iflow,int rem)
{
    if(pre==0)
        return have&&rem==0;
    if(dp[pre][now][have][iflow][rem]!=-1)
        return dp[pre][now][have][iflow][rem];
    int en=iflow? 9 : num[pre-1];
    LL ans=0;
    for(int i=0;i<=en;i++)
    {
        int tool=((rem-(i*reminder[pre-1])%13)+13)%13;
        if(now==1&&i==3)
        ans+=dfs(pre-1,i,1,iflow||i!=en,tool);
        else
        ans+=dfs(pre-1,i,have,iflow||i!=en,tool);
    }
    return dp[pre][now][have][iflow][rem]=ans;
}
void init()
{
    reminder[0]=1;
    for(int i=1;i<=10;i++)
        reminder[i]=(reminder[i-1]*10)%13;
}
LL solve(LL n)
{
    int p=0;
    memset(dp,-1,sizeof dp);
    while(n)
    {
        num[p++]=n%10;
        n/=10;
    }
    LL ans=0;
    for(int i=0;i<=num[p-1];i++)
    {
        int tool=(i*reminder[p-1])%13;
        ans+=dfs(p-1,i,0,i!=num[p-1],(13-tool)%13);
    }
    return ans;
}
int main()
{
  int n;
  init();
  while(cin>>n)
  {
      cout<<solve(n)<<'\n';
  }
   return 0;
}

추천

출처www.cnblogs.com/mqxnongmin/p/10935538.html