描述
小Ho根据最近在密码学课上学习到的知识,开发出了一款hiho密码,这款密码的秘钥是这样生成的:对于一种有N个字母的语言,选择一个长度为M的单词;将组成这个单词的所有字母按照顺序不重复的写出(即遇到相同字母时跳过);然后将字母表剩下的没有使用过的字母按照顺序在其后进行排列。
如对于有5个字母的hiho语,选择单词1, 2, 2, 4, 3(此处数字表示字母在字母表中的顺序),则秘钥为1,2,4,3,5。
但是有一天小Ho在计算出了秘钥之后,却发现他弄丢了一开始选择的单词,于是他找到了你,希望你能够帮他找到能够生成这个秘钥的最短的单词。
输入
每个输入文件包含单组测试数据。
每组测试数据的第一行为一个正整数N,意义如前文所述。
每组测试数据的第二行为N个正整数,用来描述一个秘钥,其中第i个正整数Ai表示秘钥的第i个字符在字母表中的顺序。
对于100%的数据,满足N<=1000,1<=Ai<=N。
对于100%的数据,满足对于任意1<=i, j<=N,若i≠j,则Ai≠Aj。
输出
对于每组测试数据,输出能够生成输入给出的秘钥的最短的单词(空串不认为是单词)。由于字母表没有给出,所以对于每个字母,输出其在字母表中的顺序即可(用空格隔开)。
5 1 2 4 3 5样例输出
1 2 4
#include
using namespace std;
int a[1005];
int main(){
int i,n;
while(~scanf("%d",&n)){
for(i = 0; i < n; ++i)
scanf("%d",&a[i]);
for(i = n-2; i >= 0; --i)
if(a[i] > a[i+1])
break;
if(i == -1)
i = 0;
for(int j = 0; j < i; ++j)
printf("%d ",a[j]);
printf("%d\n",a[i]);
}
return 0;
}
描述
小Hi最近在追求一名学数学的女生小Z。小Z其实是想拒绝他的,但是找不到好的说辞,于是提出了这样的要求:对于给定的两个正整数N和M,小Hi随机选取一个N的约数N',小Z随机选取一个M的约数M',如果N'和M'相等,她就答应小Hi。
小Z让小Hi去编写这个随机程序,到时候她review过没有问题了就可以抽签了。但是小Hi写着写着,却越来越觉得机会渺茫。那么问题来了,小Hi能够追到小Z的几率是多少呢?
输入
每个输入文件仅包含单组测试数据。
每组测试数据的第一行为两个正整数N和M,意义如前文所述。
对于40%的数据,满足1<=N,M<=106
对于100%的数据,满足1<=N,M<=1012
输出
对于每组测试数据,输出两个互质的正整数A和B(以A分之B表示小Hi能够追到小Z的几率)。
3 2样例输出
4 1
#include
#include
#include
#include
using namespace std;
typedef long long ll;
set s1,s2;
set::iterator it;
set getNum(ll x){
set s;
int len = sqrt(x*1.0);
for(int i = 1; i <= len; i++){
if(x % i == 0){
s.insert(i);
s.insert(x/i);
}
}
return s;
}
ll gcd(ll a,ll b){
if(b == 0)
return a;
else
return gcd(b,a%b);
}
int main(){
ll a,b;
while(~scanf("%lld%lld",&a,&b)){
s1 = getNum(a);
s2 = getNum(b);
ll len = s1.size(),cnt = 0;
for(it = s1.begin(); it != s1.end(); it++){
if(s2.find(*it) != s2.end())
cnt++;
}
len = s1.size()*s2.size();
ll tmp = gcd(len,cnt);
printf("%lld %lld\n",len/tmp,cnt/tmp);
}
return 0;
}
描述
小Hi、小Ho还有被小Hi强拉来的小Z,准备组队参加一个智力竞赛。竞赛采用过关制,共计N个关卡。在第i个关卡中,小Hi他们需要获得Ai点分数才能够进入下一关。每一关的分数都是独立计算的,即使在一关当中获得超过需要的分数,也不会对后面的关卡产生影响。
小Hi他们可以通过答题获得分数。答对一道题获得S点分数,答错一道题获得T点分数。在所有的N个关卡中,小Hi他们一共有M次答题机会。在每个关卡中,都可以在累计答题次数不超过M的情况下使用任意次的答题机会。
那么现在问题来了,对于给定的N、M、S、T和A,小Hi他们至少需要答对多少道题目才能够完成所有的关卡呢?
输入
每个输入文件包含多组测试数据,在每个输入文件的第一行为一个整数Q,表示测试数据的组数。
每组测试数据的第一行为四个正整数N、M、S和T,意义如前文所述。
第二行为N个正整数,分别表示A1~AN。
对于40%的数据,满足1<=N,M<=100
对于100%的数据,满足1<=N,M<=1000,1<=Ti<=50
对于100%的数据,满足1<=Q<=100
输出
对于每组测试数据,如果小Hi他们能够顺利完成关卡,则输出一个整数Ans,表示小Hi他们至少需要答对的题目数量,否则输出No。
1 2 10 9 1 12 35样例输出
5
#include
#define INF 0x3f3f3f3f
using namespace std;
const int N = 1005;
int dp[N][N][55];
int a[N];
int main(){
int T;
scanf("%d",&T);
while(T--){
int n, m,s,t;
scanf("%d%d%d%d",&n,&m,&s,&t);
for(int i = 1; i <= n; ++i)
scanf("%d", &a[i]);
if(n > m){
printf("No\n");
continue;
}
for(int i = 0; i <= n+1; ++i){
for(int j = 0; j <= m; ++j){
for(int k = 0; k <= a[i]; ++k){
dp[i][j][k] = INF;
}
}
}
dp[1][0][0] = 0;
for(int i = 1; i <= n; ++i){
for(int j = 0; j <= m-(n - i); ++j){
for(int k = 0; k <= a[i]; ++k){
if(dp[i][j][k] != INF){
if(t + k < a[i]){
dp[i][j + 1][k + t] = min(dp[i][j + 1][k + t], dp[i][j][k]);
}
else{
dp[i + 1][j + 1][0] = min(dp[i + 1][j + 1][0], dp[i][j][k]);
}
if(s + k < a[i]){
dp[i][j + 1][k + s] = min(dp[i][j + 1][k + s], dp[i][j][k] + 1);
}
else{
dp[i + 1][j + 1][0] = min(dp[i + 1][j + 1][0], dp[i][j][k] + 1);
}
}
}
}
}
int ans = INF;
for(int i = 0; i <= m; ++i)
ans = min(ans, dp[n + 1][i][0]);
if(ans == INF)
printf("No\n");
else
printf("%d\n",ans);
}
return 0;
}