我正在尝试如下问题: 如果出现以下情况,则说一个数字为369;
对于示例12369,383676989,396都是369个数字,而213,342143,111不是。
给定A和B找到区间[A,B]中有多少369个数字。打印答案模10 ^ 9 + 7
我接近制作dp sol的问题如下,但超出时间限制
long long rec(vector<int>&v,int index,bool status,int cnt3,int cnt6,int cnt9)
{
sz=v.size()/3;
if(cnt3>sz || cnt6>sz || cnt9>sz)
return 0;
if(index==v.size() && cnt3 && cnt3==cnt6 && cnt6==cnt9)
return 1;
else if(index==v.size())
return 0;
ll &ret=dp[index][status][cnt3][cnt6][cnt9];
if(ret==-1)
{
ret=0;
bool newstatus;
for(int i=0;i<=9;i++)
{
if(status && i>v[index] )
break;
newstatus=status && (i==v[index]);
if(i==3)
ret+=rec(v,index+1,newstatus,cnt3+1,cnt6,cnt9);
else if(i==6)
ret+=rec(v,index+1,newstatus,cnt3,cnt6+1,cnt9);
else if(i==9)
ret+=rec(v,index+1,newstatus,cnt3,cnt6,cnt9+1);
else
ret+=rec(v,index+1,newstatus,cnt3,cnt6,cnt9);
ret%=mod;
}
}
return ret;
}
有人可以帮我优化吗?
答案 0 :(得分:2)
可能阻止许多州需要探索的一个简单变化是计算m = max(cnt3,cnt6,cnt9)。
为了获得匹配计数,你必须通过m-cnt3增加cnt3,通过m-cnt6增加cnt6,通过m-cnt9增加cnt9。
你有v.size() - 索引数字仍然要分配,所以你可以在你的功能开始时添加以下额外的测试
if (v.size()-index < m*3-cnt3-cnt6-cnt9)
return 0;
此外,如果我正确理解逻辑,一旦状态变为假,您就可以选择任何数字。从这一点开始,对于cnt3,cnt6,cnt9的任何排列结果都是相同的,所以你可以对这3个数字进行排序,以便进一步减少状态空间。
同样,一旦所有计数都高于1,您就不必关心多少,以便您可以更改数字,例如:
cnt3=3,cnt6=7,cnt9=8
到
cnt3=1,cnt6=5,cnt9=6
这会导致您需要搜索更少的空间。