zoukankan      html  css  js  c++  java
  • poj 3373

    题目:http://poj.org/problem?id=3373

    题意:给出2个整数nn<10^100)和kk<10000),求满足以下条件的整数m   1mn位数相同    2m能被k整除    3、满足以上两点时,mn在相同位置的地方,数字不同的个数最少    4、满足以上三点时,m值最小

     题目里面那个mod(看的别人的)

    定义数组mod[101][10]mod[i][j]=((10^i)*j)%k,先求出:

    0   1    2    3    4    5    6    7    8    9   %k

    0   10   20   30   40   50   60   70   80   90  %k

    0   100  200  300  400  500  600  700  800  900 %k

    .....

    通过递推式mod[i][j]=(mod[i-1][j]*10)%k; 就能避免n次方的运算,节省时间。

    这样如果一个串改变一个数后可以在 O(1)的时间内求出对 kmod 的余数

    View Code
     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <iostream>
     4 #include <math.h>
     5 
     6 const int N = 110;
     7 #define _clr(a,val) (memset(a,val,sizeof(a)))
     8 typedef long long ll;
     9 
    10 using namespace std;
    11 
    12 int mod[N][10];  
    13 int num[N],path[N];
    14 int rest[N][10010];  // rest[i][j] = k 表示搜索的区间是[0,i],当前串对 m 的取余为 j 时,剩余的允许改变的数字次数为 k
    15 char str[N];
    16 int kmod,len;
    17 void init()
    18 {
    19     int i,j;
    20     for(i = 0; i < 10; i++) mod[0][i] = i % kmod;
    21     for(i = 1; i < len; i++)
    22     {
    23         for(j = 0; j < 10; j++)
    24         mod[i][j] = ((10 % kmod) * (mod[i - 1][j] % kmod)) % kmod;  
    25     }
    26 }
    27 int dfs(int pnum,int s,int pmod)  // pnum:在区间 [0,s]内剩余允许改变的数字个数  s:当前搜索的区间[0,s]  pmod:当前数字串对 k 求模的值
    28 {
    29     //cout<<"pnum = "<<pnum<<" "<<s<<" "<<pmod<<endl;
    30     if(!pmod)
    31     {
    32         for(int i = len - 1; i >= 0; i--)  printf("%d",path[i]);
    33         printf("\n");
    34         return 1;
    35     }
    36     int tmod;
    37     if(pnum == 0 || rest[pnum][pmod] > s) return 0;  // 剪枝  当前剩余的改变次数为零,或者在搜索的区间内,且当前对数字串m对 kmod 取余为 pmod时,剩余的修改(使得pmod == 0)数字次数 大于 区间时。直接返回
    38     for(int i = s; i >= 0; i--)  // 搜索比n小的数字,此时为了搜索到的解 m 是最小的,应该从区间[0,s]的第s位开始向第0位搜索,因为在相同 pnum 情况下,把高位数字变小所得到的 m 值更小。
    39     {
    40         for(int j = 0; j < num[i]; j++)
    41         {
    42             if(i == len - 1 && j == 0) continue;
    43             tmod = (pmod - (mod[i][num[i]] - mod[i][j]) + kmod) % kmod;  // 当把 m 的第i位数字 m[i] 改为j时,我们已经有((10^i)*m[i])%k的值存放在数组mod[i][m[i]]中,又有((10^i)*j)%k的值存放在数组mod[i][j]中,那么把m值改小前后的变化值为(mod[i][m[i]]- mod[i][j])
    44             path[i] = j;
    45             if(dfs(pnum - 1,i - 1,tmod)) return 1;
    46         }
    47         path[i] = num[i];
    48     }
    49     for(int i = 0; i <= s; i++)  // 搜索比 n 大的,应该从区间的开始搜索,这样能保证最小
    50     {
    51         for(int j = num[i] + 1; j < 10; j++)
    52         {
    53             if(i == len - 1 && j == 0) continue;
    54             tmod = (pmod + (mod[i][j] - mod[i][num[i]])) % kmod; 
    55             path[i] = j;
    56             if(dfs(pnum - 1,i - 1,tmod)) return 1; 
    57         }
    58         path[i] = num[i];
    59     }
    60     rest[pnum][pmod] = s + 1;
    61     return false;
    62 }
    63 int main()
    64 {
    65     int i;
    66     //freopen("data.txt","r",stdin);
    67     while(scanf("%s",str) != EOF)
    68     {
    69         len = strlen(str);
    70         scanf("%d",&kmod);
    71         init();
    72         _clr(rest,0);
    73         int tmod = 0;
    74         for(i = 0; i < len; i++)
    75         {
    76             num[i] = path[i] = (str[len - 1 - i] - '0'); 
    77             tmod = (tmod + mod[i][num[i]]) % kmod;
    78         }
    79         i = 0;
    80         while(1)
    81         {
    82             if(dfs(i++,len - 1,tmod)) break; 
    83         }
    84     }
    85     return 0;
    86 }
  • 相关阅读:
    Javascript异步与同步问题
    promise解决异步问题:.then和async_await的渊源
    vue 爬坑之路----移动端适配rem单位
    vue 爬坑之路---can't resolve 'sass-loader'
    vue-cli新建vue项目
    sublimeT3编译sass.为css到指定的路径。
    禁止滚动条滚动
    让本地的静态html页面在node上跑起来
    地址三联动,简明实现
    关于数组去重
  • 原文地址:https://www.cnblogs.com/fxh19911107/p/2633040.html
Copyright © 2011-2022 走看看