디지털 학습 노트

쓸데없는 말:
디지털 dp에서 windy만 나오고 아무것도 안 되고 띄어쓰기만 하고 기억화 검색만 하고...

요약:


대개 숫자에 대한 요구가 있고 상하한선이 특별히 크다...보통 두 가지 실현 방법이 있는데 점차적으로 추측(dp, 비교적 이해하기 쉽다. 일반적으로 이런 것을 먼저 배운다)/기억화 검색(폭력, 편리, 쓰기 쉽고 sb방법)
판자:
https://www.luogu.org/blog/mak2333/shuwei

loj#10163. Amount of Degrees


https://loj.ac/problem/10163
몇 차멱을 더하면 b진법으로 넘어갈 때 그 한 명이 1이다.답이 담긴 나무마다 여러 갈래로 돌려서 마구잡이로 굴다.대응하는 차멱 분석 & 논문에 주의하십시오:https://wenku.baidu.com/view/d2414ffe04a1b0717fd5dda8.html
#include 
#include 
#include 
using namespace std;
int f[32][32],a[32];//f: i ( i ) j 1    (          b       1)
int k,b;
int solve(int x)
{
	int len=0,kk=k;
	while (x!=0)
	{
		a[len++]=x%b; //       
		x/=b;
	}
	int ans=0; len--;
	for (int i=len;i>=0;i--)
	{
		if (a[i]==1)
		{
			ans+=f[i][kk];
			kk--;
		}
		else if (a[i]>1)
		{
			ans+=f[i+1][kk];
			break;
		}
		if (kk<0) return ans;
	}
	if (kk==0) ans++; //x    k 1
	return ans;
}
int main()
{
	for (int i=0;i<31;i++)
	{
		f[i][0]=1;
		for (int j=1;j<=i;j++) f[i][j]=f[i-1][j]+f[i-1][j-1];
	}
	int x,y;
	scanf("%d%d%d%d",&x,&y,&k,&b);
	printf("%d
",solve(y)-solve(x-1)); return 0; }

loj#10164. 디지털 게임


https://loj.ac/problem/10164
점진적 접근 방식:
//   
#include 
#include 
#include 
using namespace std;
int a[32],f[32][32];//f[i ][     ](                    ?)
int solve(int x)
{
	int len=0; memset(a,0,sizeof(a));
	while (x)
	{
		a[++len]=x%10;
		x/=10;
	}
	int ans=0;
	for (int i=len;i;i--)
	{
		if (a[i+1]>a[i]) break;
		for (int j=a[i+1];j

기억 검색:
//     
#include 
#include 
#include 
using namespace std;
int f[32][32],a[32];//f[ i  ][    ]   
int dfs(int len,int st,int lim)
{
	if (len==0) return 1;
	if (lim==0&&f[len][st]!=-1) return f[len][st];
	int ans=0,ed; if (lim==1) ed=a[len]; else ed=9;
	for (int i=st;i<=ed;i++)
	{
		if (lim==1&&i==ed) ans+=dfs(len-1,i,1);
		else ans+=dfs(len-1,i,0);
	}
	return ans;
}
int solve(int x)
{
	memset(f,-1,sizeof(f));
	int len=0;
	while (x)
	{
		a[++len]=x%10;
		x/=10;
	}
	return dfs(len,0,1);
}
int main()
{
	int x,y;
	while (scanf("%d%d",&x,&y)!=EOF)
	{
		printf("%d
",solve(y)-solve(x-1)); } return 0; }

loj#10165. Windy 수


https://loj.ac/problem/10165
점진적 접근 방식:
//  
#include 
#include 
#include 
#include 
using namespace std;
int f[32][32],a[32]; //f[  i][ i (   )   ] 
void init()
{
	for (int i=0;i<=9;i++) f[1][i]=1;
	for (int i=2;i<=31;i++)
		for (int j=0;j<=9;j++)
			for (int k=0;k<=9;k++)
				if (abs(j-k)>=2) f[i][j]+=f[i-1][k];
}
int solve(int x)
{
	memset(a,0,sizeof(a));
	int len=0;
	while (x)
	{
		a[++len]=x%10;
		x/=10;
	}
	int ans=0;
	for (int i=1;i=2) ans+=f[i][j]; //       
		if (abs(a[i+1]-a[i])<2) break;
		if (i==1) ans++;
	}
	return ans;
}
int main()
{
	init();
	int a,b;
	scanf("%d%d",&a,&b);
	printf("%d
",solve(b)-solve(a-1)); return 0; }

기억 검색 방법:
//     
#include 
#include 
#include 
using namespace std;
int f[10][10],a[10];//f[ i  ][    ]
int dfs(int len,int st,int ze,int lim)//ze        lim:       
{
	if (len==0) return 1;
	if (lim==0&&f[len][st]!=-1) return f[len][st];
	int ans=0,ed; 
	if (lim==1) ed=a[len]; else ed=9; 
	for (int i=0;i<=ed;i++) 
	{ 
		if (ze==1)
		{
			int zz=0;
			if (i==0) zz=1; 
			if (lim==1&&i==ed) ans+=dfs(len-1,i,zz,1);
			else ans+=dfs(len-1,i,zz,0);
		}
		else if (abs(st-i)>=2)
		{
			if (lim==1&&i==ed) ans+=dfs(len-1,i,0,1);
			else ans+=dfs(len-1,i,0,0);
		}
	}
	if (lim==0&&st!=0) f[len][st]=ans;
	return ans;
}
int solve(int x)
{
	memset(a,0,sizeof(a));
	int len=0;
	while (x)
	{
		a[++len]=x%10;
		x/=10;
	}
	return dfs(len,0,1,1);
}
int main()
{
	memset(f,-1,sizeof(f));
	int a,b;
	scanf("%d%d",&a,&b);
	printf("%d
",solve(b)-solve(a-1)); return 0; }

loj#10166. '한 권 통5.3 연습1'숫자 게임


https://loj.ac/problem/10166너무 많이 생각하지 말고 바로 수색하면 된다
#include 
#include 
#include 
using namespace std;
int f[32][110],a[32],n;//f[  ][  ]
int dfs(int len,int mod,int lim)
{
	if (len==0) 
	{
		if (mod==0) return 1; else return 0;
	}
	if (f[len][mod]!=-1&&lim==0) return f[len][mod];
	int ans=0,ed;
	if (lim==1) ed=a[len]; else ed=9;
	for (int i=0;i<=ed;i++)
	{
		if (lim==1&&i==ed) ans+=dfs(len-1,(mod+i)%n,1);
		else ans+=dfs(len-1,(mod+i)%n,0);
	}
	if (lim==0) f[len][mod]=ans;
	return ans;
}
int solve(int x)
{
	memset(f,-1,sizeof(f));
	memset(a,0,sizeof(a));
	int len=0;
	while (x)
	{
		a[++len]=x%10;
		x/=10;
	}
	return dfs(len,0,1);
}
int main()
{
	int a,b;
	while (scanf("%d%d%d",&a,&b,&n)!=EOF)
		printf("%d
",solve(b)-solve(a-1)); return 0; }

loj#10167. '한 권 통5.3 연습2'싫어요. 62.


https://loj.ac/problem/10167
#include 
#include 
#include 
using namespace std;
int f[7][10],a[7];//f[  i][ i   ]
int dfs(int len,int last,int lim)
{
	if (len==0) return 1;
	if (lim==0&&f[len][last]!=-1) return f[len][last];
	int ans=0,ed;
	if (lim==1) ed=a[len]; else ed=9;
	for (int i=0;i<=ed;i++)
	{
		if (i==4) continue;
		if (last==6&&i==2) continue;
		if (lim==1&&i==ed) ans+=dfs(len-1,i,1);
		else ans+=dfs(len-1,i,0);
	}
	if (lim==0) f[len][last]=ans;
	return ans;
}
int solve(int x)
{
	memset(f,-1,sizeof(f));
	memset(a,0,sizeof(a));
	int len=0;
	while (x)
	{
		a[++len]=x%10;
		x/=10;
	}
	return dfs(len,0,1);
}
int main()
{
	int a,b;
	while (scanf("%d%d",&a,&b)!=EOF&&a&&b)
	{
		printf("%d
",solve(b)-solve(a-1)); } return 0; }

loj#10168. '한 권 통5.3 연습3'미움 7


https://loj.ac/problem/10168완전 제곱 공식 2333(바보인 척.jpg) 문제풀이 & 분석:https://blog.csdn.net/ten_three/article/details/19698055 &https://www.cnblogs.com/kuangbin/archive/2013/05/01/3053233.html
#include 
#include 
#include 
using namespace std;
#define LL long long
#define mod 1000000007
struct node
{
	LL s,sum,sqrsum;//  N            
	node()
	{
		s=sum=sqrsum=-1;
	}
}f[20][10][10];//f[  ][     mod7][   mod7] 
int a[20];
LL pi[20];
node dfs(int len,int s,int qs,int lim)//        mod7    mod7      
{
	if (len==0)
	{
		node tt;
		tt.s=tt.sum=tt.sqrsum=0;
		if (s!=0&&qs!=0) tt.s=1;
		return tt;
	}
	if (lim==0&&f[len][s][qs].sqrsum!=-1) return f[len][s][qs];
	node ans; ans.s=ans.sum=ans.sqrsum=0;
	int ed=0;
	if (lim==1) ed=a[len]; else ed=9;
	for (int i=0;i<=ed;i++)
	{
		if (i==7) continue;
		/*
		 len  i f1,f2,f2...fN   len        
		       :  (f1+ i*10^(len-1) )^2+(f2+ i*10^(len-1) )^2+...+(fN+ i*10^(len-1) )^2
		              :
		N*(i*10^(len-1))^2+ f1^2+f2^2+...+fN^2+ 2*(i*10^(len-1))*(f1+f2+...fN) 
		   N     s   2*(i*10^(len-1))*(f1+f2+...fN)      sum        sqrsum 
		*/
		node tt;
		if (lim==1&&i==ed) tt=dfs(len-1,(s+i)%7,(qs*10+i)%7,1);
		else tt=dfs(len-1,(s+i)%7,(qs*10+i)%7,0);
		LL si=(i*pi[len-1])%mod;
		ans.s=(ans.s+tt.s)%mod; 
		ans.sum=(ans.sum+(tt.sum+ (si*tt.s)%mod ) %mod )%mod;
		ans.sqrsum=(ans.sqrsum+tt.sqrsum+( ((si*si)%mod*tt.s)%mod+ ((2*si)%mod *tt.sum) %mod )%mod )%mod;
	}
	if (lim==0) f[len][s][qs]=ans;
	return ans;
}
LL solve(LL x)
{
	memset(a,0,sizeof(a));
	int len=0;
	while (x)
	{
		a[++len]=x%10;
		x/=10;
	}
	node ans=dfs(len,0,0,1);
	return ans.sqrsum%mod;
}
int main()
{
	pi[0]=1;
	for (int i=1;i<=18;i++) pi[i]=pi[i-1]*10;
	int t;
	scanf("%d",&t);
	while (t--)
	{
		LL x,y;
		scanf("%lld%lld",&x,&y);
		if (x>y) swap(x,y);
		printf("%lld
",(solve(y)-solve(x-1)+mod)%mod); } return 0; }

loj#10169. '한 권 통5.3 연습4'숫자 계수


https://loj.ac/problem/10169다른 사람들은 모두 3차원 f[수위][전도제로]+10번, 매번 한 수를 찾을 때마다 나만 f[수위][기입한 숫자] 도깨비 구조체는 한 번에 모든 숫자를 찾고 전도제로를 가지지 않는다...그러니까 전도제로에 주의!!!코드에서 설명한 거 구체적으로 봐!전도 0을 넣지 않으면 그 1차원은 미리 처리하는 것을 기억해야 한다
#include 
#include 
#include 
using namespace std;
struct node
{
	bool bk;
	long long a[10];
	node()
	{
		bk=0; memset(a,-1,sizeof(a));
	}
}f[15][10];
int a[15];
long long pi[15],c[15];
node jia(node x,node y)
{
	for (int i=0;i<=9;i++) x.a[i]+=y.a[i];
	return x;
}
node dfs(int len,int x,int ze,int lim) //ze:zero      
{
	if (len==0) {node tt;tt.bk=1;memset(tt.a,0,sizeof(tt.a));tt.a[x]=1;return tt;}
	if (ze==0&&lim==0&&f[len][x].bk==1) return f[len][x];
	node ans; ans.bk=1; memset(ans.a,0,sizeof(ans.a));
	int ed;
	if (lim==1) ed=a[len]; else ed=9;
	for (int i=0;i<=ed;i++)
	{
		node tt;
		tt=dfs(len-1,i,i==0&&ze==1,i==ed&&lim==1);
		/*if (ze==1&&i==0) ;
		else if (len>1) tt.a[i]+=tt.t;*/
		if (ze==1&&i==0) ;
		else
		{
			if (len>1) 
			{
				if (lim==1&&i==ed) tt.a[i]+=c[len-1]+1;
				else tt.a[i]+=pi[len-1];
			}
		}
		ans=jia(ans,tt);
	}
	if (ze==0&&lim==0) f[len][x]=ans;
	//        /     1010  len=3,   len=2         f[2][ ].a[0]=9 (10,20,30,...,90)      18 (10,20,...,90; 01,02,...,09) 
	return ans;
}
node solve(long long x)
{
	memset(a,0,sizeof(a));
	memset(c,0,sizeof(c));
	/*for (int i=0;i<15;i++)
		for (int j=0;j<10;j++) memset(f[i][j].a,-1,sizeof(f[i][j].a)),f[i][j].bk=0;*/
	int len=0; 
	while (x)
	{
		a[++len]=x%10;
		x/=10;
		c[len]=a[len]*pi[len-1]+c[len-1]; //              (         )
	}
	return dfs(len,0,1,1);
}
int main()
{
	pi[0]=1;
	for (int i=1;i<15;i++) pi[i]=pi[i-1]*10;
 	long long x,y;
	scanf("%lld%lld",&x,&y);
	node r=solve(y),l=solve(x-1); 
	for (int i=0;i<=9;i++)
	{
		printf("%lld ",r.a[i]-l.a[i]);
	}
	printf("
"); return 0; }

끝. 꽃 뿌려!(sd 기억화 검색이 참 좋다)

좋은 웹페이지 즐겨찾기