3.5、算法练习

3.5、算法练习

一、自由练习

1)资源限制

时间限制:1.0s 内存限制:512.0MB

2)问题描述

求出区间[a,b]中所有整数的质因数分解。

3)输入格式

输入两个整数a,b。

4)输出格式

每行输出一个数的分解,形如k=a1a2a3…(a1<=a2<=a3…,k也是从小到大的)(具体可看样例)

5)样例输入

3 10

6)样例输出

3=3
4=22
5=5
6=2
3
7=7
8=222
9=33
10=2
5

7)数据规模和约定

2<=a<=b<=10000

8)解题思路

1.若为质数,直接输出;不是质数,分解为质数相乘。所以先判断质数——isPrime函数判断是否为质数

2.调用isPrime函数,并用for循环,将2—b之间的质数保存。在a—b间,判断质数并输出;若不为质数,temp=i,暂存i,用temp除以v[intex],能整除,则是所找的质数,并判断是否输出“ * ”。

提示:先筛出所有素数,然后再分解。

#include<iostream>
#include<vector>
using namespace std;

bool isPrime(int n)
{
	int i;
	for(i=2;i<=n/2;i++){
		if(n%i == 0){
			return false;
		}
	}
	if(i>n/2){
		return true;
	}
	else{
		return false;
	}
}
int main()
{
	int a,b;
	cin>>a>>b;
	vector<int> v;
	for(int i=2;i<=b;i++){
		if(isPrime(i)){
			v.push_back(i);
		}
	}
	for(int i=a;i<=b;i++)
	{
		if (isPrime(i)){//若i为质数,直接输出 
			cout<<i<<"="<<i;
		}
		else{           //i不为质数 
			cout<<i<<"=";
			int temp=i;
			int index=0; 
			while(temp != 1)
			{
				if(temp%v[index] == 0)
				{
					cout << v[index];  
					temp /= v[index];     
					index = 0; 
					if (temp != 1){
						cout<<"*";
					}
				}
				else{
					index++;
				}
		    }
	    }
	    cout<<endl; 
	}
	return 0;
} 

二、视频学习

1)视频链接

https://www.bilibili.com/video/BV1jE411g76D?p=21

2)动态规划知识点

动态规划(dynamic programming)与分治法类似,都是通过组合子问题求解原问题。(在这里,programming 指表格法。而非“编程”)。分治法是将原问题分为互不相交的子问题,递归的求解子问题,再将它们组合起来,求出原问题的解。与之相反,动态规划应用于子问题重叠的情况,即不同的子问题具有公共的子子问题,动态规划算法对每个子子问题只求解一次,将其解保存在表格中,从而不用每次求解该子子问题时都要反复计算。
总结来讲:分治法的子子问题是全新的,动态规划的子子问题是有重叠的。

使用动态规划必须满足的2条性质:

  • 最优子结构性质:问题的最优解由相关子问题的最优解组合而成,而这些子问题可以独立求解。
  • 重叠子问题:递归算法会反复求解相同的子问题,而不是一直生成新的子问题,(对比分治法:递归的每一步都生成全新的子问题),动态规划算法能够最每个子问题都只求解一次,将解存表中,需要时直接查表。但是应该注意,同一问题的其中一个子问题的解不能影响另一个子问题的解,即无关。换句话说,当前问题的每一次划分生成的子问题之间不存在重复的资源。

动态规划算法求解的基本步骤如下:

(1)划分阶段:按照问题的时间或空间特征,把问题分为若干个阶段。在划分阶段时,注意划分后的阶段一定要是有序的或者是可排序的,否则问题就无法求解。

(2)确定状态和状态变量:注意状态必须满足无后效性。

(3)确定决策:找到子问题是进行动态规划的重要一步。动态规划和递推更多应考虑本问题由哪些已解决子问题构成,而不是考虑本问题对将来哪些问题有贡献。

(4)确定边界条件,写出状态转移方程。

(5)代码编程

求解子问题的最优解
动态规划的实现有2种等价的方法:1.带备忘的自顶向下(递归)
仍按原始的递归形式,只是在递归求解过程中记录每个子问题的解,存储到数组(通常在使用前会初始化值,常用正负无穷)中。当需要一个子问题的解时,首先检查是否保存过此解,如果保存过(非初始值),则直接返回该解,节省计算时间;否则,按常规方式计算该子问题的解并记录。2.自底向上

4)问题描述

Sereja在平面上画了n个点,点i在坐标(i,0)。然后,Sereja给每个点标上了一个小写或大写英文字母。Sereja不喜欢字母"x",所以他不用它标记点。Sereja认为这些点是漂亮的,当且仅当:
  ·所有的点可以被分成若干对,使得每个点恰好属于一一对之中。
  ·在每对点中,横坐标较小的会被标上小写字母,较大的会被标上对应的大写字母。
  ·如果我们在每对点上画一个正方形,其中已知的一对点会作为正方形的相对的顶点,它们间的线段会成为正方形的对角线,那么在所有画出的正方形中不会有相交或触碰的情况。
  小Petya擦掉了一些小写字母和所有大写字母,现在Sereja想知道有多少种方法来还原每个点上的字母,使得还原后这些点是漂亮的。

5)输入格式

第一行是一个整数n,表示点的个数。
  第二行是一个长度为n的字符串,包含小写字母和问号"?",是按照横坐标递增的顺序的每个点的描述。问号表示这个点的字母被Petya擦掉了。保证输入串不含字母"x"。

6)输出格式

输出答案对4294967296取模的值。如果没有可行的方案,输出0。

7)样例输入

4
a???

8)样例输出

50

9)样例输入

4
abc?

10)样例输出

0

11)样例输入

6
abc???

12)样例输出

1

13)数据规模和约定

20个测试点的n分别为:5,10,20,50,100,200,500,1000,2000,5000,10000,20000,30000,40000,50000,60000,70000,80000,90000,100000.

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cmath>
#define PP pair<ll,int>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3fll
#define dinf 1000000000000.0
#define PI 3.1415926
#define LL unsigned int
typedef long long ll;
using namespace std;
int n,p;
LL f[200010]={1},jg=1;
char c[100010];
int main() {
	cin>>n;
	cin>>c+1;
	if(n&1)
        cout<<"0"<<endl;
	else{
		int m=n>>1;
		for(int i=1;i<=n;++i){
			if(c[i]=='?')
				for(int j=i>>1;j>=i-m&&j;j--)
					f[j]+=f[j-1];
			else
                p++;
		}
		for(int i=1;i<=m-p;i++)
			jg=jg*25;
		jg=(jg*f[m]);
		cout<<(LL)jg<<endl;
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值