https://www.luogu.com.cn/problem/P2602
挺简单 的其实,板子题
真实的模板
#include<bits/stdc++.h> using namespace std; typedef long long ll; int len,a[2000]; ll l,r,dp[20][15][25][25][20]; ll dfs(int pos,int pre,ll st,ll sum,int d,int lead,int limit) //pos搜到的位置 //pre前一位数 //st当前公差最大差值 //sum整个数字的最大价值 //d共差 //lead判断是否有前导0 //limit判断是否有最高位限制 { if(pos>len) return sum;//dp结束 //记录状态(计划搜索) //注意d有负数,最小可以到-9,所以记录时数组下标是d+10 if((dp[pos][pre][st][sum][d+10]!=-1&&(!limit)&&(!lead))) return dp[pos][pre][st][sum][d+10]; ll ret=0; int res=limit?a[len-pos+1]:9;//最高位最大值 for(int i=0;i<=res;i++) { //有前导0且这位也是前导0,一切不变只有位数变化 if((!i)&&lead) ret+=dfs(pos+1,0,0,0,-38,1,limit&&(i==res)); //有前导0但这位不是前导0(这位是数字的最高位)开始有前一位,一个数形成等差数列 else if(i&&lead) ret+=dfs(pos+1,i,1,1,-38,0,limit&&(i==res)); //之前刚搜到1位还没有共差,两位数形成等差数列,记录共差 else if(d<-9) ret+=dfs(pos+1,i,2ll,2ll,i-pre,0,limit&&(i==res)); //搜到2位以后,共差若与前两位相同当前等差数列长度增加,若公差变化则更新整个数字的最大价值,等差数列长度又变为2 else if(d>=-9) ret+=dfs(pos+1,i,(i-pre==d)?st+1:2,max(sum,(i-pre==d)?st+1:2),(i-pre==d)?d:i-pre,0,limit&&(i==res)); } //没有前导0和最高限制时可以直接记录当前dp值以便下次搜到同样的情况可以直接使用。 return (!limit&&!lead)?dp[pos][pre][st][sum][d+10]=ret:ret; } ll part(ll x) { len=0; while(x) a[++len]=x%10,x/=10; memset(dp,-1,sizeof dp); return dfs(1,0,0,0,-38,1,1);//-38是随便赋的其实赋成-10就行了…… } int main() { scanf("%d",&T); while(T--) { scanf("%lld%lld",&l,&r); //l是0的时候要特别注意! printf("%lld ",l?(part(r)-part(l-1)):(part(r)-part(l)+1)); } return 0; }
#include<iostream> #include<algorithm> #include<cstdio> #include<vector> #include<cstring> using namespace std; typedef long long ll; const int maxn = 100+11; ll dp[maxn][maxn];//第i位置的x有dp[i][][x]个 ll list[maxn]; ll dfs(int cur,int up,int lead,int val,ll sum) { //cur位置,用了sum个数字 ,lead ==1有前导0 if(cur == 0) return sum; if(!up&&lead&&dp[cur][sum] != -1) return dp[cur][sum]; int lim = 9; if(up) lim = list[cur]; ll cns =0 ; for(int i=0; i<=lim; i++) { cns += dfs(cur-1,up && (i == lim),i || lead,val,sum + ((i == val) && (i || lead))); } if(!up && lead) dp[cur][sum] = cns; return cns; } vector<ll>ins; int cal(ll n) { ll cnt =0; while(n) { list[++cnt] = n%10; n /= 10; } for(int i=0; i<10; i++) { memset(dp,-1,sizeof(dp)); ins.push_back(dfs(cnt,1,0,i,0)); } } int main() { ll l,r; scanf("%lld %lld",&l,&r); cal(r); cal(l-1); for(int i=0; i<ins.size()-10; i++) { printf("%lld",ins[i] - ins[i+10]); if(ins.size() - 9 == i) printf(" "); else printf(" "); } //printf(" "); return 0; }