zoukankan      html  css  js  c++  java
  • 【洛谷】【计数原理+Floyed】P1037 产生数

    【题目描述:】

    给出一个整数 n ((n<10^{30})) 和 k 个变换规则((k≤15))

    规则:

    一位数可变换成另一个一位数:

    规则的右部不能为零。

    例如: n=234 。有规则( k=2 ):

    2 -> 5
    3 -> 6

    上面的整数 234 经过变换后可能产生出的整数为(包括原数):

    234
    534
    264
    564

    共 4 种不同的产生数

    【问题:】

    给出一个整数 n 和 k 个规则。

    求出:

    经过任意次的变换( 0 次或多次),能产生出多少个不同整数。

    仅要求输出个数。


    [算法分析:]

    读入一个整数a,每一位分别为(a_1), (a_2), (a_3),..., (a_n)

    设置一个数组num,num[i]表示数字i有多少种变换,

    于是答案为(num[a_1] * num[a_2] * ... * num[a_n])

    写出来一看,发现在

    1234 3
    2 3
    3 2
    3 5

    这组数据下的结果是错误的,

    2变成3后,可以继续变成5,所以2能变成的值有两个

    如何统计?

    f[i][j]=1 表示数字i能变成数字j,对f数组做一遍Floyed,再遍历一遍f数组即可统计。


    [Code:]

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    int k;
    long long num1[10];
    bool a[10][10];
    char n[31], ans[205], num[10][101];
    
    int aa[205], b[205], c[205];
    char ss[205];
    //需用高精度
    void Mul(char s1[], char s2[]) {
    	memset(ss, 0, sizeof(ss));
    	memset(aa, 0, sizeof(aa));
    	memset(b, 0, sizeof(b));
    	memset(c, 0, sizeof(c));
    	int lena=strlen(s1), lenb=strlen(s2);
    	
        for(int i=0; i<lena; i++) aa[i] = s1[lena-i-1]-'0';
        for(int i=0; i<lenb; i++) b[i] = s2[lenb-i-1]-'0';
        for(int i=0; i<lena; i++)
            for(int j=0; j<lenb; j++) {
                c[i+j] += aa[i]*b[j];
                c[i+j+1] += c[i+j]/10;
                c[i+j] %= 10;
            }
        int lenc = lena+lenb;
        while(lenc>1 && c[lenc-1]==0) lenc--;
        
        for(int i=lenc-1; i>=0; i--)
        	ss[lenc-i-1] = c[i] + '0';
    }
    
    int main() {
        for(int i=0; i<=9; ++i) num1[i] = 1;
        scanf("%s%d", n, &k);
        for(int i=1; i<=k; ++i) {
            int x, y;
            scanf("%d%d", &x, &y);
            a[x][y] = 1;
        }
        for(int k=0; k<10; ++k)
        for(int i=0; i<10; ++i)
        for(int j=0; j<10; ++j)
        	a[i][j] |= (a[i][k] & a[k][j]);
        for(int i=0; i<10; ++i)
        	for(int j=0; j<10; ++j)
        		if(a[i][j] && i!=j) {
        			++num1[i];
    			}
    	for(int i=0; i<10; ++i)
    		sprintf(num[i], "%lld", num1[i]);
        int l = strlen(n);
        ans[0] = '1';
        for(int i=0; i<l; ++i) {
        	Mul(ans,num[n[i]-'0']);
        	strcpy(ans, ss);
    	}
    	cout << ans;
    }
    
  • 相关阅读:
    java nb
    hdu5293(2015多校1)--Tree chain problem(树状dp)
    点击交互的四种处理
    Java实现二维码技术探讨。
    折腾开源WRT的AC无线路由之路-1
    C语言及程序设计[套餐]课程主页
    09_Android中ContentProvider和Sqllite混合操作,一个项目调用另外一个项目的ContentProvider
    C语言打印字母金字塔(第一行是A 第二行是ABA ……)
    成员函数的const究竟修饰的是谁
    linux pdb调试总结
  • 原文地址:https://www.cnblogs.com/devilk-sjj/p/9208761.html
Copyright © 2011-2022 走看看