1. 程式人生 > 實用技巧 >2020年Acm暑期考核Hznu _2797

2020年Acm暑期考核Hznu _2797

題目連結:http://acm.hznu.edu.cn/OJ/problem.php?id=2797

題意:求1-N中有多少數字滿足:

  1. x是正整數且無前導0。
  2. x(mod 666) = S(x)。
  3. 6在x這個數的各數位上出現的總次數必須為奇數。

題解:數位dp模板題(當時考核的時候忘記了板子當場去世)

Ac程式碼:

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #include<cstring>
 5 #include<cstdio>
 6 using
namespace std; 7 #define mem(s,n) memset(s,n,sizeof s); 8 #define ios {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); } 9 typedef long long ll; 10 const int maxn=5e6+1; 11 const int Inf=0x7f7f7f7f; 12 const ll Mod=1e9+7; 13 int dp[55][2][500][667]; 14 string s; 15 int dfs(int now,int last,int sum,int
mod,bool lim)//now表示當前位數,last=0表示前面有偶數個6,last=1表示前面有奇數個6,sum表示 16 { // 前幾位數之和,mod表示對666取餘後的數字,lim判斷是否達到上界。 17 if(now==-1) 18 { 19 if(mod==sum&&(last&1)) return 1; 20 //last & 1 這個表示式可以用來判斷last的奇偶性。二進位制的末位為0表示偶數,最末位為1表示奇數
21 return 0; 22 } 23 if(!lim&&~dp[now][last&1][sum][mod]) return dp[now][last&1][sum][mod]; 24 int up=lim?s[now]-'0':9; 25 ll ans=0; 26 for(int i=0;i<=up;i++) 27 { 28 ans+=dfs(now-1,last+(i==6),sum+i,(mod*10+i)%666,lim&&i==up); 29 ans%=Mod; 30 } 31 if(!lim) dp[now][last&1][sum][mod]=ans; 32 return ans; 33 } 34 int main() 35 { 36 int t; 37 scanf("%d",&t); 38 mem(dp,-1); 39 while(t--) 40 { 41 cin>>s; 42 reverse(s.begin(),s.end());//倒置函式因為要從最高位開始。 43 printf("%d\n",dfs(s.length()-1,0,0,0,1)); 44 } 45 return 0; 46 }