终于进入了每日考试的阶段......
T1
1.1 问题描述
罗马字母I; V;X;L 分别对应着1,5,10,50。其他的字母不允许使用。一个长为n 由罗马字
母组成的字符串,我们不计顺序地计算它所对应的数值。如XXXV 代表35,IXI 代表12。注
意IX 代表11 而不是9。对于长度n 的由上述罗马字母组成的字符串最多能代表多少种数值。
1.2 输入
输入一个整数n。
1.3 输出
输出要求答案。
1.4 输入输出样例1
1.4.1 输入样例
2
1.4.2 输出样例
10
1.5 输入输出样例2
1.5.1 输入样例
10
1.5.2 输出样例
244
1.6 约定和数据范围
对于20% 的数据, n <=15,
对于60% 的数据, n <=60,
对于100% 的数据, n <=1e9
我们可以先试着写很多个for循环。。。。然后可以用肉眼观察到,从1到11是无规律的,但从11开始之后每一个数等于上一个数加上49,打表大致如下....
0,4,10,20,35,56,83,116,155,198,244,292,341,390,439,488
所以说代码就很简单了.....
#include<cstdio>
const int MAXN=1e5+7;
int a[105]={0,4,10,20,35,56,83,116,155,198,244,292};
int main()
{
//std::freopen("a.in","r",stdin);
//std::freopen("a.out","w",stdout);
int n;
std::scanf("%d",&n);
if(n<=11)
{
std::printf("%d\n",a[n]);
return 0;
}
else
{
std::printf("%I64d\n",1ll*((n-11)*49+292));
}
return 0;
}
T2
2.1 问题描述
输入x; y
比较xy 和yx 大小
2.2 输入
第一行一个整数T,
接下来T 行,每行输入两个整数x; y。
2.3 输出
输出<>=
2.4 输入输出样例1
2.4.1 输入样例
3
5 8
10 3
6 6
2.4.2 输出样例
>
<
=
2.5 约定和数据范围
对于40% 的数据, x;,y<= 50,
对于100% 的数据, 1 <=T<= 50, 1 <= x, y <= 1e9。
我们发现对于x和y来说直接取次方会非常巨大,所以为了防止溢出,我们可以选择直接取对数....
因为log函数是单增函数,所以直接取对数过后的大小关系不会变
logx^y=y*log(x);
logy^x=x*log(y);
作差就好,但是要考虑一下精度问题
代码依然简单
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
double eps=1e-8;
int main()
{
//freopen("b.in","r",stdin);
//freopen("b.out","w",stdout);
int T;
std::cin>>T;
while(T--)
{
double x,y;
std::cin>>x>>y;
double x1=y*log2(x);
double x2=x*log2(y);
if(x1-x2>eps)
{
std::printf(">\n");
}
if(x1-x2<-eps)
{
std::printf("<\n");
}
if(x1-x2>=-eps&&x1-x2<=eps)
{
std::cout<<"="<<std::endl;
}
}
return 0;
}
T3
3.1 问题描述
两个数a 和b (a < b) 被称为质数相关,是指a×p = b,这里p 是一个质数。一个集合S
被称为质数相关,是指S 中存在两个质数相关的数,否则称S 为质数无关。如2; 8; 17 质数无
关,但2; 8; 16, 3; 6 质数相关。现在给定一个集合S,问S 的所有质数无关子集中,最大的子
集的大小。
3.2 输入
第一行为一个数T,为数据组数。之后每组数据包含两行。
第一行为N,为集合S 的大小。第二行为N 个整数,表示集合内的数。
3.3 输出
对于每组数据输出一行,即最大的无关子集。
3.4 输入输出样例1
3.4.1 输入样例
3
5
2 4 8 16 32
5
2 3 4 6 9
3
1 2 3
3.4.2 输出样例
3
3
2
3.5 约定和数据范围
集合S 内的数两两不同且范围在1 到500000 之间。
对于40% 的数据, 1 <=n <= 15,
对于100% 的数据, 1 <=T <= 20, 1 <= n<= 1000。
我们发现对于任意两个数,它们的关系只有冲突或者不冲突, 所以说可以尝试使用二分图来解决这个问题
对于数字,我们用其质因数个数的奇偶来对其作区分,将奇数个质因数的数字放在一边,偶数个的则放在另一边, 然后将冲突的数通过暴力方式(n^2的两个for循环)处理出来,再跑一遍最大点独立集就好了
二分图最大点独立集=总边数-二分图最小点覆盖
所以匈牙利算法就可以搞定这道题
如果怕麻烦不想把奇数和偶数做区分的话可以不论奇偶一起建图,然后再减法的时候除以二就好
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
const int MAXN=1e3+5;
int n;
int G[1005][1005];
bool b[MAXN];
int link [MAXN];
int a[MAXN];
bool find(int x)
{
if(b[x])
{
return 0;
}
for(int i=1;i<=n;i++)
{
if(G[x][i])
{
if(!b[i])
{
b[i]=1;
if(find(link[i])||link[i]==-1)
{
link[i]=x;
return 1;
}
}
}
}
return 0;
}
const int maxn = 500001;
bool flag[maxn];
int prime[maxn], pi;
void GetPrime()
{
int i, j;
pi = 0;
memset(flag, false, sizeof(flag));
for (i = 2; i < maxn; i++)
if (!flag[i]) {
prime[i] = 1;
for (j = i; j < maxn; j += i)
flag[j] = true;
}
}
int main()
{
//std::freopen("c.in","r",stdin);
//std::freopen("c.out","w",stdout);
int T;
std::scanf("%d",&T);
GetPrime();
while(T--)
{
std::memset(G,0,sizeof(G));
std::scanf("%d", &n);
for(int i=1;i<=n;i++)
{
std::scanf("%d",a+i);
}
std::sort(a+1,a+1+n);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i==j)
{
continue;
}
int t1=a[i];
int t2=a[j];
if(t1<=t2)
{
std::swap(t1,t2);
}
if(t1%t2==0&&prime[t1/t2])
{
G[i][j]=1;
}
}
}
int cnt=0;
std::memset(link,-1,sizeof(link));
for(int i=1;i<=n;i++)
{
std::memset(b,0,sizeof(b));
if(find(i))
{
cnt++;
}
}
std::printf("%d\n",n-cnt/2);
}
return 0;
}
其实是很简单的...但是因为自己犯二丢了一百多分.....
总结一下今天犯的傻.....
第一:T1中的long long乘炸了....把1ll乘在了数组外面....(40分丢失)....
第二:T2本来写出了一条可以AC的程序,但是在最后二十分钟对自己的算法不太自信,于是为了求稳重新改写了一个暴力....结果暴力写错了......100分丢失
T3没什么好说的....大概想到正解,但是没有时间写了,于是直接状态压缩枚举所有子集....40分get。
反正作为这个难度的题目来说确实是很糟糕....(然而都是会做的....气炸.jpg)