zoukankan      html  css  js  c++  java
  • hihocoder 编程练习赛23

    第一题:H国的身份证号码I

    题意:一个N位的正整数(首位不能是0)。每位数字都小于等于K,并且任意相邻两位数字的乘积也小于等于K。按从小到大的顺序输出所有合法的N位号码,每个号码占一行。

    思路:dfs

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N = 20;
    #define LL long long 
    int n, k, a[N];
    
    void dfs(int pos)
    {
    	if (pos == n + 1){
    		for (int i = 1; i <= n; i++) printf("%d", a[i]);
    		puts("");
    		return;
    	}
    	if (pos == 1){
    		for (int i = 1; i <= k; i++){
    			a[pos] = i; dfs(pos + 1);
    		}
    	}
    	else{
    		for (int i = 0; i <= k; i++){
    			if (i * a[pos - 1] <= k){
    				a[pos] = i;
    				dfs(pos + 1);
    			}
    		}
    	}
    }
    
    int main()
    {
    	while (~scanf("%d%d", &n, &k)){
    		dfs(1);
    	}
    	return 0;
    }

    第二题:合并子目录

    题意:小Hi发现其中一些子目录只包含另一个子目录,例如/hihocoder/offer22只包含一个子目录solution,/game只包含一个子目录moba,而moba也只包含一个子目录dota2。小Hi决定把这样的子目录合并成一个子目录,并且将被合并的子目录的名字用'-'连起来作为新子目录的名字。

    思路:map数组记录前缀,num 数组记录节点孩子个数

    mop[fa][ss] //fa表示前缀序列编号,ss为当前目录

    代码:

    #include<stdio.h>
    #include<string.h>
    #include<map>
    #include<vector>
    #include<string>
    #include<iostream>
    using namespace std;
    const int N = 5e5 + 10;
    typedef long long LL;
    
    int id, n, fa, num[N];
    map<string, int> mop[N];
    char s[N]; string ss;
    map<int, string> st;
    vector<int> a[N];
    
    int main()
    {
    	while (~scanf("%d", &n)){
    		id = 0;
    		for (int i = 1; i <= n; i++){
    			scanf("%s", s);
    			fa = 0;
    			int len = strlen(s); ss = ""; s[len] = '/';
    			for (int j = 1; j <= len; j++){
    				if (s[j] == '/'){
    					if (mop[fa][ss] == 0){
    						mop[fa][ss] = ++id;
    						num[fa] ++; // 儿子个数
    					}
    					st[mop[fa][ss]] = ss;
    					fa = mop[fa][ss];
    					a[i].push_back(fa);
    					ss = "";
    				}
    				else{
    					ss += s[j];
    				}
    			}
    		}
    		for (int i = 1; i <= n; i++){
    			printf("/");
    			int size = a[i].size() - 1;
    			num[a[i][size - 1]] ++;
    			for (int j = 0; j < a[i].size() - 1; j++){
    				cout << st[a[i][j]];
    				if (num[a[i][j]] > 1) printf("/");
    				else printf("-");
    			}
    			cout << st[a[i][size]] << endl;
    		}
    	}
    	return 0;
    }

    第三题:H国的身份证号码II

    题意:第一题的扩展,对于100%的数据,1 ≤ N ≤ 1012,1 ≤ K ≤ 81,输出合法号码的总数。由于答案可能非常大,你只需要输出答案对109+7取模的结果。

    思路:数位dp, 矩阵操作

    f[i][j]:第一维表示位数,第二维表示目前的数字,值表示第 i 位为 j 时符合条件的总个数。

    #include<stdio.h>
    #include<string.h>
    #include<map>
    #include<vector>
    #include<string>
    #include<iostream>
    #include<string>
    #include<algorithm>
    using namespace std;
    const int N = 10 + 10, Z = 1e9 + 7;
    typedef long long LL;
    #define ms(x, y) memset(x, y, sizeof(x))
    #define mc(x, y) memcpy(x, y, sizeof(x))
    
    struct matrix
    {
    	LL v[N][N];
    	void O(){ ms(v, 0); };  //得到零矩阵
    	void E(){ ms(v, 0); for (int i = 0; i < 10; i++) v[i][i] = 1; } //得到单位矩阵
    	matrix operator *(const matrix &b){         //乘法
    		matrix c;
    		c.O();
    		for (int k = 0; k < 10; k++){
    			for (int i = 0; i < 10; i++){
    				for (int j = 0; j < 10; j++){
    					c.v[i][j] = (c.v[i][j] + v[i][k] * b.v[k][j]) % Z;
    				}
    			}
    		}
    		return c;
    	}
    	matrix operator ^(LL p){                   //快速幂
    		matrix x, y;
    		x.E();
    		mc(y.v, v);
    		while (p){
    			if (p & 1) x = x * y;
    			p >>= 1;
    			y = y * y;
    		}
    		return x;
    	}
    }a, b;
    
    LL n;
    int k;
    
    int main()
    {
    	while (~scanf("%lld%d", &n, &k)){
    		ms(a.v, 0); ms(b.v, 0);
    		int top = min(9, k);
    		for (int i = 1; i <= top; i++) a.v[0][i] = 1;
    		for (int i = 0; i <= top; i++){
    			for (int j = 0; j <= top; j++){
    				if (i * j <= k) b.v[i][j] = 1;
    			}
    		}
    		b = b ^ (n - 1);
    		a = a * b;
    		int ans = 0;
    		for (int i = 0; i <= top; i++) ans = (ans + a.v[0][i]) % Z;
    		printf("%d
    ", ans);
    	}
    	return 0;
    }

    第四题:观光旅行

    题意:

    思路:

  • 相关阅读:
    20200813质因数分解 --已知正整数n是两个不同的质数的乘积,试求出较大的那个质数 (奥赛一本通 P71 8)
    20200807求梯形面积,要求输入浮点数,输出精度为2位
    c++语言printf()输出格式大全 scanf()输入格式大全
    20200803给出一 名学生的语文和数学成绩,判断他是否恰好有一门课不及格(<60分),如果是输出1;否则输出0(奥赛一本通 p32 10)
    20200803-判断一个数能否同时被3,5,7整除(奥赛一本通 p32 9)
    20200802--利用公式 e=1+1/1!+1/2!+...+1/n!,求e的值, 要求保留小数点后10位(奥赛一本通 p67 2)
    20200802 给定正整数n,求不大于n的正整数的阶乘的和(即求1!+2!+...+n!),输出阶乘的和 (奥赛一本通p67 1题)
    线程
    mysql逻辑架构
    《python网络数据采集》笔记2
  • 原文地址:https://www.cnblogs.com/demian/p/7450993.html
Copyright © 2011-2022 走看看