zoukankan      html  css  js  c++  java
  • CF401D Roman and Numbers 状压DP

    CF401D

    题意翻译

    将n(n<=10^18)的各位数字重新排列(不允许有前导零) 求 可以构造几个mod m等于0的数字

    题目描述

    Roman is a young mathematician, very famous in Uzhland. Unfortunately, Sereja doesn't think so. To make Sereja change his mind, Roman is ready to solve any mathematical problem. After some thought, Sereja asked Roma to find, how many numbers are close to number n n n , modulo m m m .

    Number x x x is considered close to number n n n modulo m m m , if:

    • it can be obtained by rearranging the digits of number n n n ,
    • it doesn't have any leading zeroes,
    • the remainder after dividing number x x x by m m m equals 0.

    Roman is a good mathematician, but the number of such numbers is too huge for him. So he asks you to help him.

    输入输出格式

    输入格式:

    The first line contains two integers: n n n $ (1<=n&lt;10^{18}) $ and m m m (1<=m<=100) (1<=m<=100) (1<=m<=100) .

    输出格式:

    In a single line print a single integer — the number of numbers close to number n n n modulo m m m .

    输入输出样例

    输入样例#1: 
    104 2
    
    输出样例#1: 
    3
    
    输入样例#2: 
    223 4
    
    输出样例#2: 
    1
    
    输入样例#3: 
    7067678 8
    
    输出样例#3: 
    47
    

    说明

    In the first sample the required numbers are: 104, 140, 410.

    In the second sample the required number is 232.

    分析:

    题目描述确实比较吓人, n位数字重新排列最多可以创造出多少个%m == 0 的数;
    其实就是状态压缩;
    定义f [i] [j] , i表示一个二进制数, 1代表选这个数, j代表由n个数中选出x个组成的数%m==j;
     

    转移方程 : f[i|(1 << k)][(j * 10 + x) % m] += f[i][j];

    意义:对于第k位数x, 都可以由不选他转移到选他, 就是 i -> i |(1 << k);

    然后第二维就由 j -> (j *10 + x) % m   (显然);

    注意 : 因为状态压缩是暴力的把每一位数当成与前边的数都不一样, 比如 11 ,应该算一次, 但是我们却算了两次;

    方案 : 1. 最后除以cnt!(cnt为一个数出现了多少次)。

        2. 直接去重。

    代码奉上:
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    #define maxn (1 << 18) + 5
    #define int long long
    
    int n, m;
    
    int s[21];
    
    int f[maxn][105];
    
    char ch[20];
    
    bool vis[20];
    
    signed main()
    {
    	scanf("%s%lld", &ch, &m);
    	
    	int n = strlen(ch);
    	
    	f[0][0] = 1;
    	
    	int e = (1 << n);
    	for(register int i = 0 ; i < e ; i ++)
    	{
    		for(register int j = 0 ; j < m ; j ++)
    		{
    			memset(vis, 0, sizeof vis);
    			for(register int k = 0 ; k < n ; k ++)
    			{
    				int x = ch[k] - '0';
    				if(i & (1 << k)) continue;
    				if(i == 0 && x == 0) continue;
    				if(vis[x]) continue;
    				vis[x] = 1;
    				f[i|(1<<k)][(j*10+x)%m] += f[i][j];
    			}
    		}
    	}
    	
    	cout << f[e-1][0];
    	return 0;
    
    	
    }
    
     
  • 相关阅读:
    网站安全检测
    Centos下Subversion 服务器安装配置
    报错:1130-host ... is not allowed to connect to this MySql server 开放mysql远程连接 不使用localhost
    八个免费在线网站速度测试服务-分析影响网页加载因素提高网站访问速度
    Python处理HTML转义字符
    atitit.TokenService  token服务模块的设计
    Atitit.木马 病毒 免杀 技术 360免杀 杀毒软件免杀 原理与原则 attilax 总结
    atitit.TokenService  token服务模块的设计
    Atitit.atijson 类库的新特性设计与实现 v3 q31
    Atitit.atijson 类库的新特性设计与实现 v3 q31
  • 原文地址:https://www.cnblogs.com/BriMon/p/8933793.html
Copyright © 2011-2022 走看看