杭电oj平台上的11页题目代码:hdu-page11 (2040~2049)2046、2048


//2040
#include<iostream>
#include<algorithm>
#define MAXN 100
using namespace std;
//判断a的所有的真约数之和是否等于b
int is_N(int a,int b)
{
int sum1 = 0;//记录a的真约数之和
for (int i = 1; i <= a/2; i++)
{
if (a%i == 0)
{
sum1 += i;
}
}
if (sum1 == b)
return 1;
else
{
return 0;
}
}
int main()
{
int m;
cin >> m;
int a, b;
while (m--)
{
cin >> a >> b;
//如果两个数中任何一个数都是另一个数的真约数之和,则这两个数就是亲和数。
if (is_N(a,b)&&is_N(b,a))
{
cout << "YES" << endl;
}
else
{
cout << "NO" << endl;
}
}
return 0;
}

//2041
//思路:f1=0,f2=1;f3=2;m>2,fn=fn-1+fn-2,简单的递推
//直接递归调用会超时
/*ll recurrence(int m)
{
if (m==1)
{
return 0;
}
else if (m==2)
{
return 1;
}
else if (m==3)
{
return 2;
}
else
{
//递归调用
return recurrence(m - 1) + recurrence(m - 2);
}
}*/
#include<iostream>
#include<algorithm>
#define MAXN 40
typedef long long ll;
ll f[MAXN];
using namespace std;
void setF()
{
int i;
f[1] = 0;
f[2] = 1;
f[3] = 2;
for (i = 4; i <= MAXN ; i++)
{
f[i] = f[i - 1] + f[i - 2];
}
}
int main()
{
int n;
int m;
cin >> n;
//别忘记调用这个函数。细节问题
setF();
while (n--)
{
cin >> m;
cout << f[m] << endl;
}
return 0;
}

//2042
//思路:和前面一道题十分类似,简单的倒着递推
#include<iostream>
#include<algorithm>
#define MAXN 31
int f[MAXN];
using namespace std;
int main()
{
int n;
cin >> n;
int a;
int i;
f[0] = 3;
f[1] = 4;
f[2] = 6;
for ( i = 3; i <= 30; i++)
{
f[i] = 2 * (f[i - 1] - 1);
}
while (n--)
{
cin >> a;

cout << f[a] << endl;
}
return 0;
}

//2043
#include<stdio.h>
#include<string.h>
#define MAXN 51
char str[MAXN];
int main()
{
int m;
scanf("%d",&m);
int count;
int flag1, flag2, flag3,flag4;//分别用来标记是不是含有某一组的字符
int i;
int len;
while (m--)
{
flag1 = 0;
flag2 = 0;
flag3 = 0;
flag4 = 0;
scanf("%s", str);
len = strlen(str);
if (!(len>=8&&len<=16))
{
printf("NO ");
continue;
}
for (i = 0; i < len; i++)
{
if (str[i]>='A'&&str[i]<='Z')
{
flag1 = 1;
}
else if (str[i]>='a'&&str[i]<='z')
{
flag2 = 1;
}
else if (str[i]>='0'&&str[i]<='9')
{
flag3 = 1;
}
else if (str[i]=='~'||str[i]=='!'||str[i]=='@'||str[i]=='#'||str[i]=='$'||str[i]=='%'==str[i]=='^')
{
flag4 = 1;
}
}
//
if ((flag1 + flag2 + flag3 + flag4) >= 3)
{
printf("YES ");
}
else
{
printf("NO ");
}
}
return 0;
}

//2044
/*思路:从1到2 的可能路径(共1种):1->2;
从1到3的可能路径(共2种):1->2->3, 1->3;
从1到4的可能路径(共3种):1->2->3->4 ,1->3->4,1->2->4;
从1到5的可能路径(共5种):1->2->3->4->5,1->2->4->5,1->3->4->5,1->2->3->5,1->3->5
......
递推公式:f[n]=f[n-1]+f[n-2],注意的一点就是题目是a->b,所以看的是b-a,也就是相差的步数
*/
#include<stdio.h>
#include<string.h>
#define MAXN 51
typedef long long ll;
ll f[MAXN];
long long F(int a ,int b)
{
int n;
n = b - a;
f[1] = 1;
f[2] = 2;
if (n>2)
{
for (int i = 3; i < MAXN; i++)
{
f[i] = f[i - 1] + f[i - 2];
}
}
return f[n];
}
int main()
{
int n;
int i;
int a, b;
scanf("%d", &n);
while (n--)
{
scanf("%d%d", &a, &b);
printf("%lld ",F(a,b));
}
return 0;
}

//2045
/*思路:用递推法,1)如果前n-1个格合法,则第一个格颜色和第n-1个格的颜色不同,则此时第n个格的颜色是只有一种可能颜色(因为和第一个格的颜色不能相同,还有和其相邻的第n-1格的颜色也不能相同)
2)如果前n-1个格不合法,第n-1个格和第一个格的颜色相同,且前n-2个格合法,第n格子不能和第n-1个格和第一个格相同,所以第n个格的选择有2种*/
#include<stdio.h>
#include<string.h>
#define MAXN 51
typedef long long ll;
ll f[MAXN];

void setTab()
{
int i;
f[1] = 3;
f[2] = 6;
f[3] = 6;
for ( i = 4; i < MAXN; i++)
{
f[i] = f[i - 1] + 2 * f[i - 2];
}
}

int main()
{
int n;
setTab();
while (~scanf("%d",&n))
{
printf("%lld ", f[n]);
}
return 0;
}


//2046
#include<stdio.h>
#include<string.h>
#define MAXN 51
typedef long long ll;
ll f[MAXN];
int main()
{
int n;
f[1] = 1;
f[2] = 2;
f[3] = 3;
for (int i = 4; i < 51; i++)
{
f[i] = f[i - 1] + f[i - 2];
}
while (~scanf("%d",&n))
{
printf("%lld ", f[n]);
}

return 0;
}

//2047
/*递推:1)第n个元素是‘O’,那么第n-1个元素是‘E/F’即两种可能性,前n-2元素是正常f[n-2],故此时的总可能数是2*f[n-2];
2)第n个元素是‘E/F’即两种可能,那么前n-1个元素就没有特殊的要求即f[n-1],故此时的总可能数是2*f[n-1];
f[n]=f[n-1]+f[n-2];
*/
#include<stdio.h>
#include<string.h>
#define MAXN 51
typedef long long ll;
ll f[MAXN];
int main()
{
int n;
f[1] = 3;
f[2] = 8;
for (int i = 3; i < MAXN; i++)
{
f[i] = 2*(f[i - 1] + f[i - 2]);
}
while (~scanf("%d",&n))
{
printf("%lld ", f[n]);
}
return 0;
}

错排的递推公式

编辑
当n个编号元素放在n个编号位置,元素编号与位置编号各不对应的方法数用D(n)表示,那么D(n-1)就表示n-1个编号元素放在n-1个编号位置,各不对应的方法数,其它类推.
第一步,把第n个元素放在一个位置,比如位置k,一共有n-1种方法;
第二步,放编号为k的元素,这时有两种情况:⑴把它放到位置n,那么,对于剩下的n-1个元素,由于第k个元素放到了位置n,剩下n-2个元素就有D(n-2)种方法;⑵第k个元素不把它放到位置n,这时,对于这n-1个元素,有D(n-1)种方法;
综上得到
D(n) = (n-1) [D(n-2) + D(n-1)]
特殊地,D(1) = 0, D(2) = 1.

//2048
/*思路:题目主要的意思就是计算没有人抽到自身名字的概率,
用错排的思想,把第n个元素放到一个位置,比如位置k,一共有n-1种方法,
把位置k的元素放到某一个位置,可以放到位置n,那么剩下n-2个元素,f(n-2);
可以将其不放到位置n,这时对这n-1个元素,共有f(n-1)种方法
f(n)=(n-1)[f(n-1)+f(n-2)]
*/
#include<stdio.h>
#include<string.h>
#define MAXN 21
typedef long long ll;
ll f[MAXN];
ll factorial(int n)
{
if (n==1||n==0)
{
return 1;
}
return n*factorial(n - 1);
}
int main()
{
int n;
ll sum;
int m;
double rate;
f[1] = 0;//只有一张,故该人只能抽到自己的名字的卡片
f[2] = 1;
for (int i = 3; i < MAXN; i++)
{
f[i] = (i - 1)*(f[i - 1] + f[i - 2]);
}
scanf("%d", &n);
while (n--)
{
scanf("%d", &m);
sum = 0;
rate = 0;
//不加限制条件的总数是n!
sum = factorial(m);
rate = f[m]*100.0 / sum;
printf("%.2lf\%% ", rate);
}

return 0;
}

//2049
/*分析,该题就是求N中有M个数的错排(依然是错排,不过错排结果还要乘上C(n,m)),首先是从N个新郎中挑出会挑错新娘的M个新郎,CNM=N!/(M!*(N-M)!),
然后再求出M个数的错排个数,递推关系:f[n]=(n-1)*(f[n-1]+f[n-2]),
错排的情况:首先考虑,如果开始有n-1个新郎,并且这n-1个人都已经完成了错排(有f[n-1]种可能),现在又来了一个人,那么后来的第n个人可以通过用自己的新娘和那n-1个人的任意一个交换,来实现n个人都错排,这种情况有(n-1)*f[n-1]种可能;
另外,如果开始的n-1个人不是都错排,那么要想使第n个人过来与其中一个交换后实现错排的话就必须满足两个条件:
1.那n-1个人中只有一个人选到了自己的新娘,也就是说有n-2个人都已经错排了,
2.第n个人必须和那个选到自己的新娘的人去交换,但那个选到自己的新娘的人可以是n-1个人中的任意一个。这种情况有(n-1)*f[n-2]种可能*/
#include<stdio.h>
#include<string.h>
#define MAXN 21
typedef long long ll;
ll f[MAXN];
//阶乘函数
ll factorial(int n)
{
if (n == 1 || n == 0)
{
return 1;
}
return n*factorial(n - 1);
}
int main()
{
int c;
int n, m;
ll sum;
scanf("%d", &c);
f[0] = 0;
f[1] = 0;
f[2] = 1;
f[3] = 2;
for (int i = 4; i < MAXN; i++)
{
f[i] = (i - 1)*(f[i-1]+f[i-2]);
}
while (c--)
{
sum = 0;
scanf("%d%d", &n, &m);
sum = factorial(n) / factorial(m) / factorial(n - m);
sum *= f[m];
printf("%lld ", sum);
}
return 0;
}

一生有所追!
原文地址:https://www.cnblogs.com/BlueBlue-Sky/p/8591852.html