0 | 最大值 |
---|---|
1 | 火柴 |
2 | 游戏 |
3 | Hack比赛 |
T1
题目描述
给定n个数,{x1,x2,...,xn}要求从中选出至少一个数,至多n个数,使得乘积之和最大。
输入
第一行整数n,表示有多少个数
接下来n行,每行一个整数xi,-10 ≤xi≤ 10
输出
输出一行,表示最大乘积
样例输入
Sample Input1:
3
-1
2
-4
Sample Input2:
3
3
2
-4
样例输出
Sample Output1:
8
Sample Output2:
6
数据范围限制
对于70%的数据:1 ≤ n ≤ 9
对于100%的数据: 1 ≤ n ≤ 18,-10 ≤xi≤ 10
这题要注意,有很多陷阱
1:全是0
2:只有一个数,那个数是负数
3:一个负数,其他全是0
处理好这些,你就能对了
#include<iostream>
#include<cstdio>
using namespace std;
long long m,n,k,x=1,a[10010],y=1,o;
int main(){
freopen("max.in","r",stdin);
freopen("max.out","w",stdout);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
if(a[i]>0)x=x*a[i];
if(a[i]<0){
k++;
y=y*a[i];
}
if(a[i]==0)o++;
}
if(n==k&&k==1){
cout<<a[1];
return 0;
}
if(o==n){
cout<<0;
return 0;
}
if(k==1&&o==n-1){
cout<<0;
return 0;
}
long long max=-10000000;
if(k%2==1){
for(int i=1;i<=n;i++){
if(a[i]<0){
if(a[i]>max)max=a[i];
}
}
y=y/max;
}
cout<<x*y;
return 0;
}
T2
题目描述
给定一个N位的数,将火柴棍重新排列后,能得到的最大的数是多少?
注意不能多出或者少一位, 火柴棍要全部用上.
输入
第一行整数T,表示数据组数
接下来T行,每行一个整数N, 然后是N位数,表示原来的数,可能会有前导0,中间用空格隔开。
输出
对于每组数据,输出一行,最大的能得到的数是多少。
样例输入
3
1 3
3 512
3 079
样例输出
5
977
997
数据范围限制
对于20%的数据:1 ≤ n ≤ 10
对于60%的数据:1 ≤ n ≤ 1000
对于100%的数据: 1 ≤ n ≤ 100000,1 ≤T≤ 10
贪心加爆力
用一共的火柴棒
判断是否当前可行
可行就枚举数字(从大到小)
#include<iostream>
#include<cstdio>
using namespace std;
long long m,n,k,x,y;
int a[10]={6,2,5,5,4,5,6,3,7,6};
int main(){
freopen("match.in","r",stdin);
freopen("match.out","w",stdout);
int t;
cin>>t;
while(t--){
k=0;
string s;
cin>>n>>s;
for(int i=0;i<n;i++){
k=k+a[s[i]-48];
}
x=0;
y=n;
while(2*y<=k&&7*y>=k&&x<=n&&y>0&&k>0){
x++;
for(int j=9;j>=0;j--){
if((k-a[j]>=2*(y-1)&&(7*(y-1)>=k-a[j])&&y>1)||(y==1&&k==a[j])){
y--;
k-=a[j];
cout<<j;
break;
}
}
}
cout<<endl;
}
return 0;
}
T3
题目描述
Guyu Guo和Tube Lu正在玩一个游戏:Lu默想一个1和n 之间的数x,然后Guo尝试猜出这个数。
Guo能提出m个这样的问题: “未知数是否能被yi整除?”
游戏按照如下流程进行:Guo先给出他想问的全部m个问题,然后Lu对所有问题依次以“是”或“否”作答。得到m个问题的答案之后,Guo就要给出他的猜测。
Guo写了一个程序帮他以最优的方式提出这m个问题,现在他想知道在保证得到一个确定的答案下,最少可以问多少个问题,即m的最小值。但是Guo正忙于吃漂亮学姐送他的糖果而无暇改代码(送糖果的学姐十分多,以至于有许多糖果快要过期了),所以他找到了你,希望你来帮他解决这个问题。
输入
一行,一个整数n
输出
一行,一个整数m
样例输入
【样例输入1】
4
【样例输入2】
8
样例输出
【样例输出1】
3
【样例输出2】
6
样例1解释:
Guo依次提问能否被2,3,4整除,就可以得到确定答案。
比如Lu回答能被2,4整除,不能被3整除,则确定答案为4
样例2解释:
Guo依次提问能否被2,3,4,5,7,8整除,总共需要6次。
数据范围限制
对于20%的数据:1 ≤ n ≤ 20
对于60%的数据:1 ≤ n ≤ 1000
对于100%的数据: 1 ≤ n ≤ 100000
数学+枚举
肯定和质数有关
先用塞法塞出质数
现在来判断:
一个数,它到底说不说和之前说过的数有关
只要它之前说过的数乘起来等于它,它就不用说
那就变成了一个质数的幂在N已内出现过几次
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
bool f[100010];
long long w;
int n,ans;
int main()
{
freopen("game.in","r",stdin);
freopen("game.out","w",stdout);
cin>>n;
memset(f,false,sizeof f);
f[1] = true;
ans = 0;
for(int i=2;i<=n;i++)
if(f[i] == false)
for(int j=2;j<=n/i;j++)
f[i*j]=true;
for(int i=2;i<=n;i++)
if(f[i]==false)
{
w=i;
while(w<=n)
{
ans++;
w*=i;
}
}
cout<<ans<<endl;
return 0;
}
T4
题目描述
Codefires round马上就要结束了!ZCC已经通过做题得到了C分。但他惊讶地发现,房间里的其他选手也都解决了最难的题。ZCC根据经验断定大多数的选手都会FST的!当然,除去rating最高的选手Memset137。在此之前,ZCC想要hack他们来使他的得分更高。除了ZCC,房间里有N个选手,他们已经被按照rating从小到大排序了(所以Memset137是排在第N个的选手)。当ZCC成功hack了第i个选手时,他会获得i分的收入。你可以假设ZCC hack技术高超,百发百中,可以hack除了Memset137和自己以外的所有选手,而且在此期间没有其他选手干扰。
由于ZCC有着谦虚的美德,他不想让自己的得分太高。ZCC想要知道,存在着多少种不同的选择一些人hack的方案,使得他的得分在L和R(C≤L≤R<C+N)之间。
显然答案会很大,请输出答案对998244353取模后的结果。
输入
一行,四个整数n,c,l,r分别表示n个选手,当前分数为c,希望得分在l到r之间
输出
输出一行,方案数
样例输入
Sample Input1:
3 0 1 2
Sample Input2:
5 13 14 17
Sample Input3:
100 0 23 59
样例输出
Sample Output1:
2
Sample Output2:
6
Sample Output3:
90567
数据范围限制
对于20%的数据: 1≤N≤50;
对于50%的数据: 1≤N≤2000;
对于100%的数据: 1≤N≤100000, 1≤C≤1000000,C≤L≤R<C+N;
这肯定是一道DP
我们马上想到,设第i个数前(包括i)获得j分的方案
时间复杂度:O(N^2)
爆了
来举个列子:
假设有M个数(1~M),那它们的和就是(M-1)*M,也就是说最多选√N个数,所以可以把i的循环优化,状态变成选了i个积分为j的方案数
#include<iostream>
#include<cmath>
#include<cstdio>
using namespace std;
int m,n,k,x,y,l1,r;
int f[500][100001];
int main(){
freopen("hack.in","r",stdin);
freopen("hack.out","w",stdout);
cin>>n>>k>>l1>>r;
l1=l1-k;r=r-k;k=k-k;
f[0][0]=1;
for(int i=1;i<=sqrt(n)+131;i++){
for(int j=i;j<=r;j++){
f[i][j]=f[i][j-i]+f[i-1][j-i];
//f[i][j-i]的含义:
//相当于把选了的数向右位移1(全部加1)
f[i][j]=f[i][j]%998244353;
}
for(int j=l1;j<=r;j++){
k=k+f[i][j];
k=k%998244353;
}
}
cout<<k;
return 0;
}