zoj 3327 Friend Number 枚举 分类讨论 模拟

来源:互联网 发布:js解除绑定click事件 编辑:程序博客网 时间:2024/04/28 13:53

题意:

一个数的友好特征是它数位上的每一位数相乘后的积,如果两个数的友好特征相同那它们是friend number. 现在让我们求比输入数据大,最接近输入数据的数字。



分析:

1.如果数位上有0,友好特征是0; 如果0不在最后位,答案在原有基础上加一。如果0在最后位,在零前面的数字加一。模拟。

if(zero)      {        int z,o=len-1 ;        if(zero==1&&number[len-1]=='0') o--;number[o]++;       for(int i=o;i>=0;i--)           {           z=number[i]-'0';           if(z>=10) { if(i) number[i-1]++;number[i]='0';}}   if(z>=10) printf("1");  }

2.数位上没有零。数位上每一个数 x>=0&&x<=9,因此友好特征的素因子只有 2,3,5,7。如果知道一个数的素因子,再将它的约数拼成最小的数 ,那要将最大的约数放在最后。


所以我们可以从倒数第2位开始枚举(枚举从低到高,保证最小),计算后面数字的友好特征的素因子,再计算最小数字的长度,如果小于等于后面数字长度,即为解。

计算 素因子():

void plus1(int x){for(int i=1;i<=4;i++)    while(x%e[i]==0)    {    p[i]++;x /=e[i]; }}

代码:

#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>#define inf 100000000using namespace std;int e[5]={1,2,3,5,7};int p[10];int vis[10],ans;void plus1(int x){for(int i=1;i<=4;i++)    while(x%e[i]==0)    {    p[i]++;x /=e[i]; }}void pp(int x){ ans=0; int ee[10]={0}; for(int i=1;i<=4;i++) { while(x%e[i]==0) { ee[i]++; x /=e[i]; }ee[i] =p[i]-ee[i];if(ee[i]<0) { ans=inf;return;} }vis[9]=ee[2]/2;ee[2] %=2;    vis[8]=ee[1]/3;ee[1] %=3;    vis[4]=ee[1]/2;ee[1] %=2;    vis[6]=min(ee[1],ee[2]);ee[1] -=vis[6];ee[2] -=vis[6];    vis[2]=ee[1];vis[3]=ee[2];vis[5]=ee[3];vis[7]=ee[4];    for(int i=1;i<=9;i++) ans +=vis[i];}int nu(){int x;if(vis[9]) vis[x=9]--;else if(vis[8]) vis[x=8]--;else if(vis[7]) vis[x=7]--;else if(vis[6]) vis[x=6]--;else if(vis[5]) vis[x=5]--;else if(vis[4]) vis[x=4]--;else if(vis[3]) vis[x=3]--;else if(vis[2]) vis[x=2]--;else x=1;return x;}int main(){   int t;   char number[1005];   scanf("%d",&t);   while(t--)   {     ans=0;  int le=0,flag=0,zero=0,len;     scanf("%s",number);     len=strlen(number);     for(int i=1;i<=4;i++) p[i]=0,vis[i]=0;     for(int i=len-1;i>=0;i--) if(number[i]=='0') zero++;   if(zero)      {        int z,o=len-1 ;        if(zero==1&&number[len-1]=='0') o--;number[o]++;       for(int i=o;i>=0;i--)           {           z=number[i]-'0';           if(z>=10) { if(i) number[i-1]++;number[i]='0';}}   if(z>=10) printf("1");  }  else{     for(int i=len-1;i>=0;i--)     {     le++;     plus1(number[i]-'0');     if(i<len-1)      {     int ss=number[i]-'0';     for(int j=ss+1;j<=9;j++)     {     pp(j);       if(ans<=le-1)     {         flag=1;number[i]=j+'0';for(int j1=len-1;j1>=i+1;j1--)  number[j1]=nu()+'0';break;}if(flag) break;}}if(flag) break;ans=0;  }  if(!flag)   {  printf("1");pp(1);  for(int j1=len-1;j1>=0;j1--) number[j1]=nu()+'0';  }    }  printf("%s\n",number);    }   return 0;}


1 0
原创粉丝点击