标签:starting out 计算 main 代码 test i++ efi ios
题目描述:
输入样例:
输出样例:
思路:
设f[i] [j] [k] 表示第i位,首元素为j,当前计算的值为k
转移方程f[i][j][l]+=f[i-1][k][l-(j<<(i-1))];
先预处理,由于多组数据,预处理一下前缀和,查询时先求和一下整数的部分,其余之后再求:
int i,j,p,di=1,ans=1 + (calc(n)<=m); for(i=1;b[i]<=n;i++) for(j=1;j<10;j++) ans+=f[i][j][m]; for(;i;i--) { p=n/b[i-1]%10; for(j=di;j<p;j++)ans+=f[i][j][m]; m-=p<<(i-1),di=0;//求残余的部分,每次减去之前加的m if(m<0)break; } return ans;
代码:
#include<cstdio> #include<iostream> #include<cstdlib> using namespace std; int f[10][10][10500],b[100]; int calc(int x) { int t=1,tot=0; while(x) tot+=(x%10)*t,x/=10,t<<=1; return tot; } void init() { int i,j,k,l; f[0][0][0]=b[0]=1; for(int i=1;i<10;i++) { b[i]=b[i-1]*10; for(j=0;j<10;j++) for(k=0;k<10;k++) for(l=j<<(i-1);l<=10000;l++) f[i][j][l]+=f[i-1][k][l-(j<<(i-1))]; } for( i=1;i<10;i++) for( j=0;j<10;j++) for( k=1;k<=10000;k++) f[i][j][k]+=f[i][j][k-1]; } int sum(int n,int m) { int i,j,p,di=1,ans=1 + (calc(n)<=m); for(i=1;b[i]<=n;i++) for(j=1;j<10;j++) ans+=f[i][j][m]; for(;i;i--) { p=n/b[i-1]%10; for(j=di;j<p;j++)ans+=f[i][j][m]; m-=p<<(i-1),di=0; if(m<0)break; } return ans; } int main() { int T,i,a,bb; init(); scanf("%d",&T); for(i=1;i<=T;i++){ scanf("%d%d",&a,&bb); printf("Case #%d: %d\n",i,sum(bb,calc(a))); } return 0; }
标签:starting out 计算 main 代码 test i++ efi ios
原文地址:https://www.cnblogs.com/yelir/p/11417523.html