这一题我个人认为是比较难的了。
暴力去拿部分分也是可以的。
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; int main() { int n; while(scanf("%d",&n)!=EOF){ int ans=0; for(int i=13;i<=n;i+=13){ int j=i,x,y=-1; while(j){ x=j%10;j/=10; if(x==1&&y==3){ans++;break;} y=x; } } printf("%d\n",ans); } return 0; } //超级慢
然而这样子绝对是不好的,打表都比这好。
不过还是正解最好了。
#include<iostream> #include<cstring> #include<cstdio> using namespace std; int f[15][10][2][13]; int md[15];//md用于保存10^n void init(){//初始化 md[0]=1; for(int i=1;i<=13;i++) md[i]=(md[i-1]*10)%13; memset(f,0,sizeof(f)); f[0][0][0][0]=1;//切记是f[0][0][0][0]而不是f[0][0][1][0] //因为一开始没有包含13 for(int i=1;i<=13;i++) for(int j=0;j<=9;j++) for(int k=0;k<=9;k++) for(int l=0;l<13;l++){ int val=(j*md[i-1])%13; f[i][j][1][l]+= f[i-1][k][1][(13+l-val)%13]; if(j==1&&k==3) f[i][j][1][l]+= f[i-1][k][0][(13+l-val)%13]; else f[i][j][0][l]+= f[i-1][k][0][(13+l-val)%13]; //这里用(13+l-val)因为有可能l<val } } int solve(int n){ int digit[15];//从低到高保存n的每一位 int len=0,ans=0,mod=0; int t=0;//t保存是否在高位出现过13 while(n!=0){//统计n的位数 digit[++len]=n%10;n/=10; } digit[len+1]=0;//方便处理 for(int i=len;i>=1;i--){//枚举当前位数 for(int j=0;j<digit[i];j++){ ans+=f[i][j][1][(13-(mod*md[i]%13))%13]; if(t||(j==3&&digit[i+1]==1)) ans+=f[i][j][0][(13-(mod*md[i]%13))%13]; } if(digit[i]==3&&digit[i+1]==1)t=1;//如果高位出现过13,t=1 mod=(mod*10+digit[i])%13;//更改mod } return ans; } int main() { int n; init(); while(scanf("%d",&n)!=EOF){ printf("%d\n",solve(n+1)); //因为是solve是计算区间[0,n)的,所以要n+1 } return 0; }
本文由Yzyet编写,网址为www.cnblogs.com/Yzyet。非Yzyet同意,禁止转载,侵权者必究。
时间: 2024-10-24 01:46:35