有更新 浙大月赛 ZOJ Monthly, June 2012 on June 24

zoj 3611

 

同类型的题目

poj 2688

化简模型即可得这样的问题,一幅图给定起点 终点 ,求起点到终点最多经过几个点,如果两种方案经过的点数相同,选路径总长短的

注意,这幅图最多只有12个点,所以立刻可以想到用状态压缩来做

dp[i][j]表示以i为终点的路径 为j状态(经过了那些点)时的最短路径

ps:在预处理最短路的时候不要将'$'算进去,就看成一个普通的可以走的格子就可以了

因为可能会出现如下情况,'$'的费用会算了四次,所以还是先数一下有几个'$'然后再独立算吧

 

 

View Code
#include<cstdio>
#include<cstring>
#include<map>
#include<queue>
#include<vector>
#include<algorithm>
using namespace  std;
typedef long long lld;
int dir[4][2]={1,0,0,1,-1,0,0,-1};
const lld inf = 2139062143;
char g[510][510];
int di[510][510];
bool vis[510][510];
map<int,pair<int,int> > mp;
struct point{
    int x,y;
    point(){}
    point(int a,int b):x(a),y(b){}
};
int n,m;
queue<point> pq;
vector<pair<int,int> > edge[20];
point fr;
void make(int dx,int dy){
    point t;
    t.x=fr.x+dx;
    t.y=fr.y+dy;
    if(t.x>n || t.x<1 ||t.y<1 ||t.y>m || g[t.x][t.y]=='W' || g[t.x][t.y]=='#') return ;
    if(di[t.x][t.y]>di[fr.x][fr.y]+1){
        di[t.x][t.y]=di[fr.x][fr.y]+1;
        if(!vis[t.x][t.y]){
            pq.push(point(t.x,t.y));
            vis[t.x][t.y]=true;
        }
    }
}
void delt(char op){
    if(op=='U') make(-1,0);
    if(op=='D') make(1,0);
    if(op=='L') make(0,-1);
    if(op=='R') make(0,1);
}
void spfa(point src){
    while(!pq.empty()) pq.pop();
    memset(di,127,sizeof(di));
    memset(vis,0,sizeof(vis));
    vis[src.x][src.y]=1;di[src.x][src.y]=0;pq.push(src);
    while(!pq.empty()){
        fr=pq.front();pq.pop();
        vis[fr.x][fr.y]=false;
        if(g[fr.x][fr.y]=='0' || g[fr.x][fr.y]=='$'){
            for(int i=0;i<4;i++){
                make(dir[i][0],dir[i][1]);
            }
        }
        else {
            delt(g[fr.x][fr.y]);
        }
    }
}
int dp[13][(1<<13)];
bool v[20][(1<<13)];
void  solve(int n,int s,int t){
    memset(v,0,sizeof(v));
    memset(dp,127,sizeof(dp));
    queue<pair<int,int> > Q;
    Q.push(make_pair(s,(1<<s)));v[s][1<<s]=true;
    dp[s][1<<s]=0;
    while(!Q.empty()){
        int fr=Q.front().first ;
        int st=Q.front ().second;
        Q.pop();v[fr][st]=false;
        int sz=edge[fr].size();
        for(int i=0;i<sz;i++){
            int node = edge[fr][i].first,w=edge[fr][i].second;
            if(dp[fr][st]+w<dp[node][st|(1<<node)]){
                dp[node][st|(1<<node)]=dp[fr][st]+w;
                if(!v[node][st|(1<<node)]){
                    v[node][st|(1<<node)]=true;
                    Q.push(make_pair(node,st|(1<<node)));
                }
            }
        }
    }
    int num=0,ans=inf;
    for(int i=0;i<(1<<n);i++)if(dp[t][i]!=inf){
        int sum=0;
        for(int j=0;j<n;j++)if(i&(1<<j))sum++;
        if(sum>num){
            num=sum;
            ans=dp[t][i];
        }
        else if(sum==num){
            if(dp[t][i]<ans)ans=dp[t][i];
        }
    }
    num-=2;
    if(ans!=inf) printf("%d\n",ans+num*2);
    else    printf("-1\n");
}
int main(){
    int i,j,k,x1,x2,y1,y2;
    while(scanf("%d%d",&n,&m)!=EOF){
        mp.clear();
        for(i=0;i<=13;i++) edge[i].clear();
        k=0;
        for(i=1;i<=n;i++){
            scanf("%s",g[i]+1);
            for(j=1;j<=m;j++){
                if(g[i][j]=='$')
                    mp[k++]=make_pair(i,j);
            }
        }
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        mp[k++]=make_pair(x1,y1);mp[k++]=make_pair(x2,y2);//start: k-2 , end : k-1
        for(i=0;i<k;i++){
            int x=(int)mp[i].first,y=(int)mp[i].second;
            point tmp=point(x,y);
            spfa(tmp);
            for(j=0;j<k;j++){
                edge[i].push_back(make_pair(j,di[mp[j].first][mp[j].second]));    
            }
        }
        solve(k,k-2,k-1);
    }
}

 

 

zoj 3612 

简单题,求第k大的数

 

View Code
#include<cstdio>
#include<cstring>
#include<map>
#include<algorithm>
using namespace  std;
typedef long long lld;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn = 10010;
int sum[maxn<<2];
int num[maxn];
struct PP{
    char s[10];
    int v;
}q[maxn];
void build(int l,int r,int rt){
    sum[rt]=0;
    if(l==r) return ;
    int m=(l+r)>>1;
    build(lson);
    build(rson);
}
void update(int pos,int f,int l,int r,int rt){
    sum[rt]+=f;
    if(l==r){
        return ;
    }
    int m=(l+r)>>1;
    if(pos<=m) update(pos,f,lson);
    else update(pos,f,rson);
}
int query(int k,int l,int r,int rt){
    if(l==r) {
        return  l;
    }
    int m=(l+r)>>1;
    if(k<=sum[rt<<1]) return query(k,lson);
    else return query(k-sum[rt<<1],rson);
}
void print(int tot){
    if(sum[1]%2){
        int id=query(sum[1]/2+1,0,tot-1,1);
        printf("%d\n",num[id]);
    }
    else {
        int id1=query(sum[1]/2,0,tot-1,1);
        int id2=query(sum[1]/2+1,0,tot-1,1);
        if((num[id1]+num[id2])%2==0) printf("%lld\n",((lld)num[id1]+(lld)num[id2])/2);
        else printf("%.1lf\n",1.0*((lld)num[id1]+num[id2])/2);
    }
}
map<lld,int> mp;
int main()
{
    int t,n,i,j,k;
    scanf("%d",&t);
    while(t--)
    {
        mp.clear();
        scanf("%d",&n);
        for(i=0;i<n;i++){
            scanf("%s%d",q[i].s,&q[i].v);
            num[i]=q[i].v;
        }
        sort(num,num+n);
        int tot=unique(num,num+n)-num;
        build(0,tot-1,1);
        for(i=0;i<n;i++)
        {
            if(q[i].s[0]=='r'){
                if(mp[q[i].v]){
                    mp[q[i].v]--;
                    int pos=lower_bound(num,num+tot,q[i].v)-num;
                    update(pos,-1,0,tot-1,1);
                    if(sum[1]==0) puts("Empty!");
                    else {
                        print(tot);
                    }
                }
                else{
                    puts("Wrong!");
                }
            }
            else {
                mp[q[i].v]++;
                int pos=lower_bound(num,num+tot,q[i].v)-num;
                update(pos,1,0,tot-1,1);
                print(tot);
            }
        }
    }
    return 0;
}

 

zoj 3614

预处理两个sum

sum1[i][j]表示(1,1)到(i,j)的和。

sum2[i][j]表示(1,1) 到(i,j)的平方和。

算方差的时候将各项拆开,同类项合并,分别相加就好了

求子矩阵内的最大值,开始的时候用二维线段树写了,但是一直超时,经分析,原因如下:

复杂度为q*n*m*log(n)*log(m); 

而RMQ预处理之后 是O(1)的回答,为 n*m*log^2+q*n*m少了点常数,所以用了RMQ之后立刻就过了

View Code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long lld;
inline int max(int a,int b){return a>b?a:b;}
int sum1[310][310],g[310][310];
int f[310][310][9][9];
lld sum2[310][310];
int n,m;
void init(){
    int i,j;
    for(i=1;i<=n;i++) sum1[i][0]=0,sum2[0][i]=0;
    for(j=1;j<=m;j++) sum1[0][j]=0,sum2[0][j]=0;
    for(i=1;i<=n;i++)for(j=1;j<=m;j++){
    sum1[i][j]=sum1[i-1][j]+sum1[i][j-1]+g[i][j]-sum1[i-1][j-1];
    sum2[i][j]=sum2[i-1][j]+sum2[i][j-1]+g[i][j]*g[i][j]-sum2[i-1][j-1];
    }
}
int log2(int x)  
{  
    int k=0;  
    while((1<<(k+1))<x)++k;  
    return k;  
}  
void ST()  
{  
    int i,j,u,v,logn=log2(n),logm=log2(m);  
    for(u=0;u<=logn;++u)  
        for(v=0;v<=logm;++v)  
            if(u+v)for(i=1;i+(1<<u)-1<=n;++i)  
                for(j=1;j+(1<<v)-1<=m;++j)  
                if(v==0)f[i][j][u][v]=max(f[i][j][u-1][v],f[i+(1<<(u-1))][j][u-1][v]);  
                else f[i][j][u][v]=max(f[i][j][u][v-1],f[i][j+(1<<(v-1))][u][v-1]);  
}  
int get(int r1,int c1,int r2,int c2)  
{  
    int k=log2(r2-r1+1),t=log2(c2-c1+1);  
    int a=max(f[r1][c1][k][t],f[r1][c2-(1<<t)+1][k][t]);  
    int b=max(f[r2-(1<<k)+1][c1][k][t],f[r2-(1<<k)+1][c2-(1<<t)+1][k][t]);  
    return max(a,b);  
}  
int main(){
    int i,j,k,cases=1;
    while(scanf("%d%d",&n,&m)!=EOF){
        for(i=1;i<=n;i++)for(j=1;j<=m;j++){
                scanf("%d",&g[i][j]);
                f[i][j][0][0]=g[i][j];
            }
        ST();

        init();
        int q,x,y;
        printf("Case %d:\n",cases++);
        scanf("%d",&q);
        while(q--){
            int ansx=-1,ansy=-1;
            double ret=100000000000.0;
            scanf("%d%d",&x,&y);
            for(j=1;j<=n-x+1;j++){
                for(k=1;k<=m-y+1;k++){
                     lld sum=sum2[j+x-1][k+y-1]+sum2[j-1][k-1]-sum2[j-1][k+y-1]-sum2[j+x-1][k-1];
                     lld   s=sum1[j+x-1][k+y-1]+sum1[j-1][k-1]-sum1[j-1][k+y-1]-sum1[j+x-1][k-1];
                     int mx=get(j,k,j+x-1,k+y-1);
                     sum-=mx*mx;  s-=mx;
                     double aver=1.0*s/(x*y-1);
                     double ans=sum+(x*y-1)*aver*aver-2.0*s*aver;
                     ans/=(x*y-1);
                     if(ans<ret){
                         ansx=j;ansy=k;
                         ret=ans;
                     }
                }
            }
            printf("(%d, %d), %.2lf\n",ansx,ansy,ret);
        }
    }
    return 0;
}

 

 

 zoj 3615 KMP + KM

建图利用 字符串的匹配KMP算法来搞

然后就是最优匹配KM的模板了

注:建图的时候可以把女孩到男孩的边也加进男孩到女孩的边权中,因为匹配了一对就表示双方的权值都会加上

由于很久没写这种模板,建图建错,WA了 7 次,囧。。。。

View Code
#include<cstdio>
#include<cstring>
const int inf = ~0u>>2;
int n,m;
int p[30];
char sent[210][10010],b[30];
char boy[210][25],girl[210][25];
void getp(char b[]){
    p[1]=0;
    int i,j=0;
    for(i=2;i<=m;i++){
        while(j>0&&b[j+1]!=b[i]) j=p[j];
        if(b[j+1]==b[i]) j+=1;
        p[i]=j;
    }
}
int first;
int kmp(char a[],char b[]){
    int i,j=0,cnt=0;
    first=0;
    for(i=1;i<=n;i++){
        while(j>0&&b[j+1]!=a[i]) j=p[j];
        if(b[j+1]==a[i]) j+=1;
        if(j==m){
            if(!first) first=i-m+1;
            cnt++;
            j=p[j];
        }
    }
    return cnt;
}
int solve(int flag,int x,int y,int mm)
{
    if(flag)
    {
        memset(p,0,sizeof(p));
        n=strlen(sent[x]+1);
        m=strlen(girl[y]+1);
        getp(girl[y]);
        int num=kmp(sent[x],girl[y]);
        if(first) return first*num;
    }
    else 
    {
        memset(p,0,sizeof(p));
        n=strlen(sent[mm+x]+1);
        m=strlen(boy[y]+1);
        getp(boy[y]);
        int num=kmp(sent[mm+x],boy[y]);
    /*    puts(boy[y]+1);
        printf("%d %d %d %d\n",flag,x,y,first*num);    
        for(int i=1;i<=m;i++) printf("%d ",p[i]);puts("");*/
        if(first) return first*num;
    }

}
inline int MIN(int a,int b){return a<b?a:b;}
inline int max(int a,int b){return a>b?a:b;}
const int INF = 100000000;
#define MAX 250
int match[MAX];
bool sx[MAX],sy[MAX];
int lx[MAX],ly[MAX],map[MAX][MAX];
bool path(int u,int n)
{
    sx[u]=true;
    for(int v=0;v<n;v++)
        if(!sy[v]&&lx[u]+ly[v]==map[u][v])
        {
            sy[v]=true;
            if(match[v]==-1||path(match[v],n))
            {
                match[v]=u;
                return true;
            }
        }
        return false;
}
int KM(int n)
{
    int i,j;
    for(i=0;i<n;i++)
    {
        lx[i]=-INF;
        ly[i]=0;
        for(j=0;j<n;j++)
            if(lx[i]<map[i][j])
                lx[i]=map[i][j];
    }
    memset(match,-1,sizeof(match));
    for(int u=0;u<n;u++)
        while(1)
        {
            memset(sx,0,sizeof(sx));
            memset(sy,0,sizeof(sy));
            if(path(u,n))
                break;
            int dmin=INF;
            for(i=0;i<n;i++)
                if(sx[i])
                    for(j=0;j<n;j++)
                        if(!sy[j])
                            dmin=MIN(lx[i]+ly[j]-map[i][j],dmin);
                        for(i=0;i<n;i++)
                        {
                            if(sx[i])
                                lx[i]-=dmin;
                            if(sy[i])
                                ly[i]+=dmin;
                        }
        }
        int sum=0;
        for(j=0;j<n;j++)
            sum+=map[match[j]][j];
        return sum;
}
int main()
{
    int i,j,m,n;
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        memset(map,0,sizeof(map));
        for(i=0;i<m;i++) 
        {
            scanf("%s",boy[i]+1);
            getchar();
            int len=strlen(boy[i]+1);
            boy[i][len]=0;
            gets(sent[i]+1);
        }
        for(i=0;i<n;i++)
        {
            scanf("%s",girl[i]+1);
            getchar();
            j=strlen(girl[i]+1);
            girl[i][j]=0;
            gets(sent[i+m]+1);
        }
    //    for(i=0;i<m;i++) puts(boy[i]+1);
    //    for(i=0;i<n;i++) puts(girl[i]+1);
        int ans=0,num;
        for(i=0;i<m;i++){
            for(j=0;j<n;j++){
                map[i][j]=solve(1,i,j,m);
            //    printf("%d %d %d\n",i,j,map[i][j]);
            }
        }
    //    puts("");
        for(i=0;i<n;i++){
           for(j=0;j<m;j++){
                map[j][i]+=solve(0,i,j,m);
            //    printf("%d %d %d\n",i,j,map[j][i]);
           }
        }
        ans=KM(max(m,n));
        printf("%d\n",ans);
    }
    return 0;
}

 

 zoj 3616 

主要要解决的问题:给你一个矩阵,有些位置的数可能为负,求一个和最大的子矩阵,要求这个子矩阵中不包含负数

注意题目给出的数据范围100行 2000列,行很少,所以可以考虑暴力枚举子矩阵的行数(起始行,和终止行),然后再从第一列开始枚举,直到某一列出现负数,就计算一下与出现负数的上一列之间的和,判断是否满足男女人数的要求,再用来更新答案即可,效率又排第一了,呵呵

View Code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int l[2010],r[2010];
int sum[110][2010],num[110][2010];
int c1[110][2010],boy[110][2010],girl[110][2010];
int f[110][2010];
int n,m,b,g;
void init(){
    int i,j;
    for(i=1;i<=n;i++) sum[i][0]=0,c1[i][0]=0,boy[i][0]=0,girl[i][0]=0;
    for(j=1;j<=m;j++) sum[0][j]=0,c1[0][j]=0,boy[0][j]=0,girl[0][j]=0;
    for(i=1;i<=n;i++)for(j=1;j<=m;j++){
    boy[i][j]=boy[i-1][j]+boy[i][j-1]+(!f[i][j])-boy[i-1][j-1];
    girl[i][j]=girl[i-1][j]+girl[i][j-1]+(f[i][j])-girl[i-1][j-1];
    c1[i][j]=c1[i-1][j]+c1[i][j-1]+(num[i][j]<0)-c1[i-1][j-1];
    sum[i][j]=sum[i-1][j]+sum[i][j-1]+num[i][j]-sum[i-1][j-1];
    }
}
bool judge(int s,int t,int col){//判断第col列,从s行到t行是否有负数
    return c1[t][col]-c1[s-1][col]-c1[t][col-1]+c1[s-1][col-1];
}
int calc(int s,int t,int pre,int now){//计算子矩阵的和
    return sum[t][now]-sum[s-1][now]-sum[t][pre-1]+sum[s-1][pre-1];
}
bool ok(int s,int t,int pre,int now){//是否至少有b个男孩,g个女孩
     return (boy[t][now]-boy[s-1][now]-boy[t][pre-1]+boy[s-1][pre-1]>=b &&
         girl[t][now]-girl[s-1][now]-girl[t][pre-1]+girl[s-1][pre-1]>=g);
}
int main(){
    while(scanf("%d%d%d%d",&n,&m,&b,&g)!=EOF){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                scanf("%d%d",&num[i][j],&f[i][j]);f[i][j]--;
            }
        }
        init();
        int ans=0;
        for(int i=1;i<=n;i++){
            for(int j=i;j<=n;j++){
                int pre=0;
                for(int k=1;k<=m;k++){
                    if(judge(i,j,k)){
                        if(k==1 || judge(i,j,k-1)) pre=k;
                        else {
                        int s=calc(i,j,pre+1,k-1);
                        if(s>ans && ok(i,j,pre+1,k-1)) ans=s;
                         pre=k;
                        }
                    }
                }if(!judge(i,j,m)){
                    int s=calc(i,j,pre+1,m);
                    if(s>ans && ok(i,j,pre+1,m)) ans=s;
                }
            }
        }
        if(ans!=0) printf("%d\n",ans);
        else puts("No solution!");
    }
    return 0;
}

 

zoj 3617

贪心,假如在当前关卡冲能量(hp),当前每秒所能冲的hp值应该是局部最大,尽量让在当前关卡所充的能量能坚持到下一个比他大的关卡处

View Code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf  =  ~0u>>2;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn = 100010;
int Max[maxn<<2];
void pushup(int rt){
    Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);
}
void update(int p,int val,int l,int r,int rt){
    if(l==r){
        Max[rt]=val;
        return ;
    }
    int m=(l+r)>>1;
    if(p<=m) update(p,val,lson);
    else update(p,val,rson);
    pushup(rt);
}
int query(int L,int R,int val,int l,int r,int rt){
    if(Max[rt] < val) return -1;
    if(l==r){
        return l;
    }
    int m=(l+r)>>1;
    int ret=-1;
    if(L<=m) ret=query(L,R,val,lson);
    if(ret!=-1)  return ret;
    if(R>m) ret=query(L,R,val,rson);
    return ret;
}
struct data{
    int x,y;
}in[maxn];
long long sum[maxn];
int main(){
    int n,hp;
    while(scanf("%d%d",&n,&hp)!=EOF){
        int mxhp=hp;
        sum[0]=0;
        for(int i=1;i<=n;i++){
            scanf("%d%d",&in[i].x,&in[i].y);
            sum[i]=sum[i-1]+in[i].x;
            update(i,in[i].y,1,n,1);
        }
        int ans=0;
        for(int i=1;i<=n;i++){
            hp-=in[i].x;
            int id=query(i+1,n,in[i].y,1,n,1);
            if(id==-1) id=n;
            if(sum[id]-sum[i]>=hp){
                long long  t=(sum[id]-sum[i]-hp)/in[i].y+1;
                if(t*in[i].y+hp<=mxhp){
                    ans+=t;
                    hp+=t*in[i].y;
                }
                else {
                    t=(mxhp-hp)/in[i].y;
                    ans+=t;
                    hp+=t*in[i].y;
                    id=query(i+1,n,mxhp-hp,1,n,1);
                    if(id==-1) id=n;
                    if(hp<=sum[id]-sum[i]){
                        hp=mxhp;
                        ans++;
                    }
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

 

 zoj 3618 

字符串的哈希,字符串的哈希的题目做过好几次了

CF7D   题解

CF196D  题解

这道题目搞了半天,正着哈希反着哈希都无法有效的搞定,都无法转换成前缀的哈希

然后我发现我被坑了,题目告诉你那样子哈希,你不一定要那样子哈希啊。。。

基本思路是每到一个位置,判断一下是否存在以这个位置结尾的子串哈希值为N,当然这个哈希值还是题目的哈希值

这样的话就可以通过前缀的哈希值减去一个值(N转换过来的)变成前缀,再判断这个值被映射了几次

讲的很模糊

举个例子吧

BCBC   b=2 p=1000000007  n=199=66*2+67

n为BC的哈希值,不难看出答案为2,即有两个子串哈希值为199

可以构造一个哈希的方法

sum[1]=66*2^3

sum[2]=66*2^3+67*2^2

sum[3]=66*2^3+67*2^2+66;

sum[4]=66*2^3+67*2^2+66*2+67

这样子就能保证减去n转换过来的一个值后,能转换成前缀的哈希,相当于 i 前缀减去一个以i结尾的子串还是一个前缀,只需要判断前缀被哈希了几次即可

注意这题还有个坑,字符可能为空格,所以要用gets(),代码超短,就不贴了,有需要可以向我要

 

 

zoj 3620

注意要建双向边,我Wa了一次

和第一题如出一辙(好奇怪干嘛出两个),稍微改了下条件,第一题还难一点呢

 

 

zoj 3621 

首先要会求n为10进制时n!的末尾共有几个0,10 有2 5两个质因子,假设n!有x个2  y个5  所以n!末尾的0的个数就是min(x,y)

然后联想到末尾的0都是由进制数产生的,所以对进制数分解质因子,n!中哪个因子的个数最少就是答案

还要 注意比如18 进制 2 3 3 ,两个3一个2才能产生一个0

View Code
#include<cstdio>
#include<cstring>
#include<map>
#include<queue>
#include<algorithm>
using namespace  std;
typedef long long lld;
int num[100];
int tot;
map<int,int> mp;
void init(int k){
    tot=0;mp.clear();
    for(int i=2;;i++){
        if(k%i==0){
            num[++tot]=i;
            while(k%i==0){
                mp[tot]++;
                k/=i;
            }
            if(k==1) return ;
        }
    }
}
void Min(lld &a,lld b){
    if(a==-1||b<a) a=b;
}
int main(){
    int i,j,k;
    char s[100];
    while(scanf("%s%d",s,&k)!=EOF){
        int len=strlen(s);
        lld sum=0;
        for(i=0;i<len;i++){
            if(s[i]>='A' && s[i]<='Z'){
                sum=sum*k+s[i]-'A'+10;
            }
            else if(s[i]>='a' && s[i]<='z'){
                sum=sum*k+s[i]-'a'+36;
            }
            else sum=sum*k+s[i]-'0';
        }
        init(k);
        lld ans=-1;
        for(i=1;i<=tot;i++){
            lld cnt=0;
            lld tmp=sum;
            while(tmp){
                tmp/=num[i];
                cnt+=tmp;
            }
            cnt/=mp[i];
            Min(ans,cnt);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

 

 

 

 

 

 

posted @ 2012-06-25 22:04  Because Of You  Views(2065)  Comments(1Edit  收藏  举报