vijos P1129 产生数

8 篇文章 0 订阅
4 篇文章 0 订阅

题意:输入n组数a->b,再输入一串数字,其中数字可由a变换为b,求存在多少种情况。

链接:https://vijos.org/p/1129

思路:可转化为一个最短路径问题。将10个数字的变换情况分别看作一个节点,利用floyd求出所有通路,统计每种数的变换可能,再转化为组合问题。

注意点:求组合时要考虑溢出的可能。用大数乘法。

以下为AC代码:

评测状态Accepted
题目P1129 产生数
递交时间2014-11-06 17:14:05
代码语言C++
评测机VijosEx
消耗时间15 ms
消耗内存280 KiB
评测时间2014-11-06 17:14:07
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <deque>
#include <list>
#include <cctype>
#include <algorithm>
#include <climits>
#include <queue>
#include <stack>
#include <cmath>
#include <set>
#include <iomanip>
#include <cstdlib>
#include <ctime>
using namespace std;

struct node
{
    char a;
    char b;
    friend bool operator < ( const node &a, const node &b )
    {
        return a.b < b.b;
    }
} p[20];

bool adj[10][10];
int ans[50];

void muti ( int m )
{
    int tmp = 0;
    for ( int i = 0; i < 50; i ++ )
    {
        tmp = ans[i] * m + tmp;
        ans[i] = tmp % 10000;
        tmp = tmp / 10000;
    }
}

void floyd ( int n )
{
    for ( int i = 0; i < n; i ++ )
    {
        adj[i][i] = true;
        for ( int j = 0; j < n; j ++ )
        {
            for ( int k = 0; k < n; k ++ )
            {
                if ( adj[j][i] && adj[i][k] )
                {
                    adj[j][k] = true;
                }
            }
        }
    }
}

int main()
{
    int num[15] = { 0 };
    string str;
    while ( cin >> str )
    {
        int n;
        cin >> n;
        memset ( adj, 0, sizeof ( adj ) );
        memset ( ans, 0, sizeof ( ans ) );
        for ( int i = 0; i < n; i ++ )
        {
            cin.clear();
            cin >> p[i].a;
            cin.clear();
            cin >> p[i].b;
            adj[p[i].a-'0'][p[i].b-'0'] = true;
        }
        floyd( 10 );
        for ( int i = 0; i < 10; i ++ )
        {
            num[i] = 0;
            for ( int j = 0; j < 10; j ++ )
            {
                if ( adj[i][j] )
                {
                    num[i] ++;
                }
            }
        }
        ans[0] = 1;
        for ( int i = 0; i < (int)str.size(); i ++ )
        {
            muti ( num[str[i] - '0'] );
        }
        int k;
        for ( k = 49; k >= 0 && ans[k] == 0; k -- );
        printf ( "%d", ans[k] );
        k --;
        for ( ; k >= 0; k -- )
        {
            printf ( "%04d", ans[k] );
        }
        cout << endl;
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值