版权声明:本文为博主原创文章,如果转走了就评论说一声就好了哈。 https://blog.csdn.net/qq_36124802/article/details/82804451
HDU3652:
T组数据
找到1-n之间包含13这个子串并且能被13整除的数字个数。
dp[i][j][k]表示计算到第i位,目前%结果为j且需要k状态才满足题意。
这里k为2:表示不缺13这个子串的个数
k为1:表示上一个数末尾为1,此时缺一个3可以组成13
k为0:表示之前没有13,仍然缺13.
dps(i,mod,k,limit)表示找到i位,%为mod,状态满足k的个
-
#include<bits/stdc++.h> using namespace std; const int maxn=5e5+7; typedef long long ll; ll dp[25][25][3]; ll digit[25]; //dp[i][j][k], //i位,mod13的结果为j, //0:不包含1,3. //1:末尾为1 //2:剩下的里面有1,3了 ll yu[25]; ll dfs(ll len,ll mod,ll end_x,bool limit){ if(len==0){ //cout <<" --- " << len <<" "<<mod << " "<<end_x<<" "<<limit << endl; if(mod==0&&end_x==2)return 1; return 0; } if(!limit&&dp[len][mod][end_x])return dp[len][mod][end_x]; //,没有限制长度并且后面记录过了 ll up_bound,cnt=0; if(limit) up_bound=digit[len]; else up_bound=9; ll new_x,new_mod; // cout <<"in " <<len <<" mod= " <<mod <<" end_x" << end_x <<" "<<up_bound << endl; for(ll i=0;i<=up_bound;i++){ new_mod=((mod+i*yu[len-1]))%13; /* cout <<i <<"aaa " <<len <<" mod= " <<mod <<" end_x" << end_x <<" "<<up_bound << " " <<new_mod <<endl;*/ if(end_x==2) //如果已经全部有了,那就随便要,但是%13==0 cnt+=dfs(len-1,new_mod,2,limit&&i==up_bound); else if(end_x==1&&i==3) //已经末尾为1,那么要3可以变成2 cnt+=dfs(len-1,new_mod,2,limit&&i==up_bound); else if(i==1)//不管前面是什么,要个1进去就只缺一个3了 cnt+=dfs(len-1,new_mod,1,limit&&i==up_bound); else //啥也没有那么啥也都还要 cnt+=dfs(len-1,new_mod,0,limit&&i==up_bound); } if(!limit)dp[len][mod][end_x]=cnt; //注意这里需要不为limit,不然后面会有限制 return cnt; } ll solve(ll x){ int k=0; long long g1=1; yu[0]=g1; for(int i=1;i<=12;i++){ g1*=10LL; yu[i]=g1%13; } while(x){ digit[++k]=x%10; x/=10; } dfs(k,false,false,true); } int main(){ int i,j,k,f1,f2,f3,f4,t1,t2,t3,t4; //freopen("in.txt","r",stdin); int T; ll g1,g2,g3,g4; while(cin >> g1){ cout << solve(g1) << endl; } return 0; }
-
给一个[L,R],求L->R之间非0数量小于3的个数
-
dp[i][j]表示dp到第i位,目前剩j个非0位
-
那么每次循环中如果是否0,且num>0,则还可以有非0位,否则不加这个数字
-
如果是循环到0,num可以获取的数量不变,正常计算即可
-
#include<bits/stdc++.h> using namespace std; const long long maxn=5e5+7; typedef long long ll; ll dp[25][4]; ll digit[25]; ll yu[25]; ll dfs(ll len,ll num,bool limit){ if(len==0){ return 1; } if(!limit&&dp[len][num])return dp[len][num]; //,没有限制长度并且后面记录过了 ll up_bound,cnt=0; if(limit) up_bound=digit[len]; else up_bound=9; for(long long i=0;i<=up_bound;i++){ if(i!=0){ if(num>0) cnt+=dfs(len-1,num-1,limit&&i==up_bound); }else cnt+=dfs(len-1,num,limit&&i==up_bound); } if(!limit)dp[len][num]=cnt; //注意这里需要不为limit,不然后面会有限制 return cnt; } ll solve(ll x){ long long k=0; long long g1=1; while(x){ digit[++k]=x%10; x/=10; } dfs(k,3,true); } int main(){ long long i,j,k,f1,f2,f3,f4,t1,t2,t3,t4; //freopen("in.txt","r",stdin); long long T; ll g1,g2,g3,g4; cin >> T; while(T--){ cin >> g1>> g2; g3=solve(g1-1); g4=solve(g2); cout << g4-g3<< endl; } return 0; }
3.codeforces55d(挖坑
-
想了好一会以为对的做法其实还是太年轻。
-
开始想dp[i][j]表示i位,可以mod(j),这里j为二进制表示0~9的集合,的数量,
-
这里出现一个问题,如果之前为1x,那么dp[1][3]为(10、11、12、15)4个数字,二
-
如果前面的数字变了,其实就也许可以比如104mod4这样的出现了,也就是说前面的数字改变了,模数很可能是改了的。
-