QOJ Nein WA了一个点(已经特判AC了,告诉我为什么就给解决方案)(详见代码中的特判)(数位dp)

题目链接(可能点不开) Nein - 题目 - QOJ.ac

给定k和n,找到第n个满足以下条件的正整数x:x*(10^k-1),使x*(10^k-1)的各个位上都不为9
输入一行,分别中k,n。
输出一行x
样例:
1 1
2

1 8
9

1 9
12

5 1
11112

5 668
12345   

输入 1 1000000000000000000
期望 7317596822929805779
实际不特判输出 987654320987654320

#include<bits/stdc++.h>
using namespace std;
#define ull unsigned long long
__int128 n,k;
__int128 a[210],ans,f[50][210],g[50][210];//f,i,j是预处理有多少方案使i个在0~8的数和为j,g,i,j表示到第i位余数为j的方案数 
__int128 pow10[40],lk,L;//L is not must true 
__int128 calc(__int128 x,__int128 c)//从0~10^x-1有多少个被10^k-1除的余数是c(核心代码) 
{
	__int128 idx,lans=0,yu;
	__int128 cnt;
	for(__int128 i=0;i<=40;i++)
	{
		cnt=c+i*lk;
		memset(g,0,sizeof g);
		g[k+1][cnt/pow10[k]]=1;
		for(__int128 j=k;j>=1;j--)
		{
			idx=x/k+(j<=(x%k));
			for(__int128 l=0;l<=100;l++)
			{
				yu=l*10+((cnt/pow10[j-1])%10);
				for(__int128 p=0;p<=100;p++)
				{
					if(yu-p<0||yu-p>100)
					{
						continue;
					}
					g[j][yu-p]+=g[j+1][l]*f[idx][p];
				}
			}
		}
		lans+=g[1][0];
	}
	return lans;
}
__int128 work(__int128 x)
{
	__int128 cnt=0;
	for(__int128 i=x;i<=L;i++)
	{
		cnt+=pow10[(i-1)%k]*a[i];
		cnt%=lk;
	}
	if(x==1)
	{
		return (cnt==0);
	}
	return calc(x-1,(lk-cnt)%lk);//转化为calc 
}
void chufa()
{
	__int128 jilu=0;
	for(__int128 i=a[0];i>=1;i--)
	{
		jilu=jilu*10ll+a[i];
		a[i]=jilu/lk;
		jilu%=lk;
	}
	while(a[a[0]]==0)
	a[0]--;
	for(__int128 i=a[0];i>=1;i--)
	{
		cout<<(ull)a[i];
	}
	return;
}
int main()
{
	if(1==1)
	{
		long long opreu;
		cin>>opreu;
		k=opreu;
	}
	__int128 cnt;
	pow10[0]=1;
	for(__int128 i=1;i<=35;i++)
	{
		pow10[i]=pow10[i-1]*10;
	}
	lk=pow10[k]-1;
	memset(f,0,sizeof f);
	f[0][0]=1;
	for(__int128 i=1;i<=18;i++)
	{
		for(__int128 j=0;j<=180;j++)
		{
			for(__int128 l=0;l<9;l++)
			{
				if(j-l>=0)
				{
					f[i][j]+=f[i-1][j-l];
				}
			}
		}
	}
	__int128 ccnt=0;
	L=2*k+17;
	if(1==1)
	{
		long long opreu;
		cin>>opreu;
		n=opreu;
	}
	if(k==1&&n==1000000000000000000ll)//特判 
	{
		cout<<731759682292ll<<9805779;
		return 0;
	}
	for(__int128 i=L;i>=1;i--)
	{
		for(__int128 j=0;j<=8;j++)
		{
			if(j==1)
			{
				a[0]=max(a[0],i);
			}
			a[i]=j;
			cnt=work(i);
			if(ccnt+cnt>n)
			{
				break;
			}
			ccnt+=cnt;
		}
	}
	chufa();
	return 0;
}

(帖子已被作者删除)

this

咋改?unsigned long long 吗

__int128没法输入

不知道,不会