1月24日 upc

upc训练赛第十二场


前言

今天的题不会的是真不会,像后两个英文题还有C题和H题,劝退啊。


A 马拦过河卒(暴力+动态规划)

棋盘上A点有一个过河卒,需要走到目标B点。卒行走的规则:可以向下、或者向右。同时在棋盘上C点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。棋盘用坐标表示,A点(0, 0)、B点(n, m)(n, m为不超过20的整数),同样马的位置坐标是需要给出的。现在要求你计算出卒从A点能够到达B点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步。
输入
6 6 3 3
输出
3
其实就是跟走棋盘一样 关系方程是f[i][j]=f[i-1][j]+f[i][j-1],所以dfs也行

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int a[101][101];
    long long int f[101][101];    //记得开long long 
    int dx[8]= {1,2,2,1,-1,-2,-2,-1};   //偷懒
    int dy[8]= {2,1,-1,-2,-2,-1,1,2};   
    int n,m,x,y;
    cin >> n >> m >> x >> y;
    memset(a,0,sizeof(a));    //初始化
    memset(f,0,sizeof(f));    //初始化
    for(int i=0; i<=7; i++)
    {
        if(x+dx[i]>=0&&x+dx[i]<=n&&y+dy[i]>=0&&y+dy[i]<=m)
            a[x+dx[i]][y+dy[i]]=1;      //不能走的马控制得八个点标记上
    }
    a[x][y]=1;       // 马那个点也不行
    f[0][0]=1;        
    for(int i=0; i<=n; i++)
    {
        for(int j=0; j<=m; j++)
        {
            if(i-1>=0&&a[i-1][j]==0)    
                f[i][j]+=f[i-1][j];    
            if(j-1>=0&&a[i][j-1]==0)
                f[i][j]+=f[i][j-1];  
        }
    }
        
   cout<<f[n][m]<<endl;
    return 0;
}

B 选数(dfs)

已知 n 个整数 x1,x2,…,xn,以及一个整数 k(k<n)。从 n 个整数中任选 k 个整数相加,可分别得到一系列的和。例如当 n=4,k=3,4 个整数分别为 3,7,12,19 时,可得全部的组合与它们的和为:
3+7+12=22
3+7+19=29
7+12+19=38
3+12+19=34。
现在,要求你计算出和为素数共有多少种。
例如上例,只有一种的和为素数:3+7+19=29)。**
输入
4 3
3 7 12 19
输出
1
写得有点麻烦了,dfs经典题,好像是noip普及组2002

#include <bits/stdc++.h>
using namespace std;
int n,k;
long long  a[25],ans;
bool vis[25];
bool fun(long long n)     //判断质数
{
    if(n==1||n==0)
    {
        return false;
    }
    else
    {
        for(int i=2; i*i<=n; i++)
        {
            if(n %i==0)
            {
                 return false;
            }
        }
        return true;
    }
}
void dfs(int s,int t,long long sum)   //  s是位置,t是计数的,sum累加数
{
    if(t==k)
    {
        if(fun(sum))
        {
            ans++;
        }
        return;    
    }
    for(int i=s+1; i<=n; i++)
    {
        if(!vis[i])
        {
            vis[i] = true;    //貌似没必要???
            dfs(i,t+1,sum+a[i]);   
            vis[i] = false;
        }
    }
}
int main()
{
    cin >> n >> k;
    for(int i=1; i<=n; i++)
    {
        scanf("%lld",&a[i]);
    }
    dfs(0,0,0);   
    cout << ans << endl;
    return 0;
}


C.产生数(dfs)

给出一个整数 n(n<1030) 和 k 个变换规则(k<=15)。
规则:
一位数可变换成另一个一位数:
规则的右部不能为零。
例如:n=234。有规则(k=2):
2-> 5
3-> 6
上面的整数 234 经过变换后可能产生出的整数为(包括原数):
234
534
264
564
共 4 种不同的产生数
问题:
给出一个整数 n 和 k 个规则。
求出:
经过任意次的变换(0次或多次),能产生出多少个不同整数。
仅要求输出个数。
这个没弄出来,感觉应该是搜素,待补

D 级数求和 (循环,枚举)

已知:Sn= 1+1/2+1/3+…+1/n。显然对于任意一个整数K,当n足够大的时候,Sn大于K。
现给出一个整数K(1<=k<=15),要求计算出一个最小的n;使得Sn>K。

水题,记得用double

E 幸运数字 (枚举)

出现好几次了。。。

F 对撞(模拟,函数)

小明发明了一个数字对撞机,两个位数相同的整数可以进行碰撞。碰撞过程中,将两个 整数的每一位进行比较,较小的那个数字会被撞得粉碎,较大的数字保留下来(如果两数 相同,都会保留)。例如下面例子中:两个整数 13570 和 21673 碰撞后,对应数位上较小的值已经消失,碰撞的结果为:第一 个数字剩下 37,第二个数字剩下 2673。
现在小明想让你写一个程序来显示数字碰撞机的结果,输入两个整数,输出碰撞后的两 个数字。(注意最终结果不能包含多余的前导 0)
输入
样例1
13570
21673
样例2
300
500
样例3
1234
5678
输出
37
2673
0
500
BOOM
5678
铁定有人觉得样例把情况给全了,其实这题巨坑,补两组数据吧
输入
0030
0400
输出
3
40
思路:就是把情况考虑全,开两个数组存两组数,按题意模拟后,扫一遍看一下是不是没有数了,再看一下是不是应该输出的是0,其他情况输出即可。

#include<bits/stdc++.h>
using namespace std;
string s1,s2;
int a[1005],b[1005];
int n1,n2;
int fun(int a[])
{
    for(int i=0;i<n1;i++)
    {
        if(a[i] != -1)
            return 0;
    }
    return 1;
}
int jk(int a[])
{
    for(int i=0;i<n1;i++)
    {
        if(a[i] != 0 && a[i] != -1)  //不是0就是-1 那就是0;
            return 0;
    }
    return 1;
}
int main()
{
    int flag=0;
    cin >> s1 >> s2;   //别问我为啥吗,无奈之举,
    n1 = s1.length();   
    n2 = s2.length();
    for(int i=0;i<n1;i++)
    {
        a[i] = s1[i]-'0';   //记得转换下
    }
    for(int i=0;i<n2;i++)
    {
        b[i] = s2[i]-'0';
    }
    for(int i=0;i<n1;i++)
    {
        if(a[i]>b[i])    //废掉的标记一下
        {
            b[i]=-1;    
        }
        else if(a[i]<b[i])
        {
            a[i]=-1;
        }
    }
    if(fun(a)==1)   //特判1
    {
        cout << "BOOM" << endl;
    }
     else if(jk(a)==1)   //特判2
    {
        cout << 0 << endl;
    }
     else
    {
        for(int i=0;i<n1;i++)
    {
            if(a[i] != -1)
            {
                if(a[i] != 0)     //别输出一个前导0;
                {
                    flag = 1;
                    cout << a[i];
                }
                else if(a[i] == 0 && flag == 1)
                {
                    cout << a[i];
                }

            }
       }
       cout << endl;
    }
    flag=0;     //下面的就是改个数组名了。
    if(fun(b)==1)
    {
        cout << "BOOM" << endl;
    }
    else if(jk(b)==1)
    {
        cout << 0 << endl;
    }
    else
    {
        for(int i=0;i<n1;i++)
      {
            if(b[i] != -1)
            {
                if(b[i] != 0)
                {
                    flag = 1;
                    cout << b[i];
                }
                else if(b[i] == 0 && flag == 1)
                {
                    cout << b[i];
                }

            }
       }
       cout << endl;
    }
    return 0;
}

G 差值求和(规律)

**小明最近学习了差的绝对值,|a-b|表示a-b的绝对值,若a-b>=0,则|a-b|=a-b;若a-b<0,则|a-b|=-(a-b)。
经过几次练习,小明已经熟练掌握了差的绝对值,现在他找来了N个整数,开始任意取出两个数,求差的绝对值,再将所有差的绝对值相加。例如N=4,有4个整数,分别是1,2,3,4。任取两个数有6种取法,|1-2|=1,|1-3|=2,|1-4|=3,|2-3|=1,|2-4|=2,|3-4|=1,它们的和就是10。
由于运算量太大,累坏了小明。请你写一个程序帮他计算一下吧。

输入
第一行一个整数n,表示有n个整数
第二行n个整数,表示小明写下的n个整数

输出
输出一个数,表示任意两数差的绝对值之和。
样例输入 Copy
【样例1】
3
3 1 2
【样例2】
4
1 2 3 4
样例输出 Copy
【样例1】
4
【样例2】
10
提示
样例1解释:|3-1|=2,|3-2|=1,|1-2|=1,答案为4

对于40%的数据,n<=1000,0<=每个数<=1000
对于70%的数据,输入数据保证第二行的n个数字从小到大有序。
对于100%的数据,n<=100000,0<=每个数<=1,000,000,000**
这看一眼数据就知道暴力是不可能的,先升序排序,找规律,首先肯定是一个循环搞定的,我们要算两个数的绝对值之和,那就是挑两个数大减小,排序后最大的数在最后一位,他要减前面n-1个数数就是(n-1)a[n],当然这是一个极限情况,对于任意的a[i],要减i-1个数,被减n-i次,所以就是(2*i-n-1)a[i]

#include<bits/stdc++.h>
using namespace std;
long long int a[1000002];
int main()
{
     long long int n,sum=0;
     cin >> n;
     for(int i=1;i<=n;i++)
     {
         cin >> a[i];
     }
     sort(a+1,a+n+1);
     for(int i=1;i<=n;i++)
     {
         sum+=a[i]*(2*i-1-n);
     }
     cout << sum << endl;
	return 0;
}

H 取数游戏(这个不会)

J Unhappy Hacking I (模拟)

Sig has built his own keyboard. Designed for ultimate simplicity, this keyboard only has 3 keys on it: the 0 key, the 1 key and the backspace key.
To begin with, he is using a plain text editor with this keyboard. This editor always displays one string (possibly empty). Just after the editor is launched, this string is empty. When each key on the keyboard is pressed, the following changes occur to the string:
The 0 key: a letter 0 will be inserted to the right of the string.
The 1 key: a letter 1 will be inserted to the right of the string.
The backspace key: if the string is empty, nothing happens. Otherwise, the rightmost letter of the string is deleted.
Sig has launched the editor, and pressed these keys several times. You are given a string s, which is a record of his keystrokes in order. In this string, the letter 0 stands for the 0 key, the letter 1 stands for the 1 key and the letter B stands for the backspace key. What string is displayed in the editor now?

Constraints
1≤|s|≤10 (|s| denotes the length of s)
s consists of the letters 0, 1 and B.
The correct answer is not an empty string.
输入
01B0
输出
00
按照题意模拟即可

#include<stdio.h>
#include <bits/stdc++.h>
using namespace std;
int main()
{
   char a[109];
   char b[109];
   int sum=0;
   cin >> a;
   for(int i=0;i<strlen(a);i++)
   {
       if(a[i]=='0'||a[i]=='1')
       {
           b[sum]=a[i]-'0';
           sum++;
       }
       else if(a[i]=='B')
       {
           if(sum==0)
           {
               continue;   
           }
           else
           {
               sum--;
           }
       }
   }
   for(int i=0;i<sum;i++)
    {
        printf("%d",b[i]);
    }

}

K Be Together(循环)

Evi has N integers a1,a2,…,aN. His objective is to have N equal integers by transforming some of them.
He may transform each integer at most once. Transforming an integer x into another integer y costs him (x−y)2 dollars. Even if ai=aj(i≠j), he has to pay the cost separately for transforming each of them.
Find the minimum total cost to achieve his objective.

Constraints
1≤N≤100
−100≤ai≤100
输入
2
4 8
输出
8
其实找到一个数使数组中每个数跟它差的和最小,那就找平均数呗。但是找平均数到底向哪里去整是个问题,所以都试一下再比较

#include<bits/stdc++.h>
using namespace std;
long long int a[1009],sum1=0,sum=0,n,sum2=0,k,t;
int main()
{
  	cin >> n;
  	for(int i=0;i<n;i++)
  	{
  		cin >> a[i];
		sum+=a[i];
	}
    t=sum/n;     
	for(int i=0;i<n;i++)
	{
        k=a[i]-t;
		sum1+=k*k;
	}
	 t++;
	for(int i=0;i<n;i++)
	{
        k=a[i]-t;
		sum2+=k*k;
	}
	sum1=min(sum1,sum2);
	cout << sum1 << endl;;
	return 0;
}


总结

第一次写博客,嘿嘿。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
面对Hash函数领域取得的重大研究进展,Crypto 2004 会议总主席StorageTek高级研究员Jim Hughes 17 早晨表示,此消息太重要了,因此他已筹办该会成立24年来的首次网络广播(Webcast )。Hughes在会议上宣布:“会中将提出三份探讨杂凑碰撞(hash collisions )重要的研究报告。”其中一份是王小云等几位中国研究人员的研究发现。17晚,王小云教授在会上把他们的研究成果做了宣读。这篇由王小云、冯登国、来学嘉、于红波四人共同完成的文章,囊括了对MD5、HAVAL-128、 MD4和RIPEMD四个著名HASH算法的破译结果。在王小云教授仅公布到他们的第三个惊人成果的时候,会场上已经是掌声四起,报告不得不一度中断。报告结束后,所有与会专家对他们的突出工作报以长时的热烈掌声,有些学者甚至起立鼓掌以示他们的祝贺和敬佩。当人们掌声渐息,来学嘉教授又对文章进行了一点颇有趣味的补充说明。由于版本问题,作者在提交会议论文时使用的一组常数和先行标准不同;在会议发现这一问题之后,王小云教授立即改变了那个常数,在很短的时间内就完成了新的数据分析,这段有惊无险的小插曲倒更加证明了他们论文的信服力,攻击方法的有效性,反而凸显了研究工作的成功。   会议结束时,很多专家围拢到王小云教授身边,既有简短的探讨,又有由衷的祝贺,褒誉之词不绝。包含公钥密码的主要创始人R. L. Rivest和A. Shamir在内的世界顶级的密码学专家也上前表示他们的欣喜和祝贺。   国际密码学专家对王小云教授等人的论文给予高度评价。   MD5的设计者,同时也是国际著名的公钥加密算法标准RSA的第一设计者R.Rivest在邮件中写道:“这些结果无疑给人非常深刻的印象,她应当得到我最热烈的祝贺,当然,我并不希望看到MD5就这样倒下,但人必须尊崇真理。”   Francois Grieu这样说:“王小云、冯登国、来学嘉和于红波的最新成果表明他们已经成功破译了MD4、MD5、HAVAL-128、RIPEMD-128。并且有望以更低的复杂度完成对SHA-0的攻击。一些初步的问题已经解决。他们赢得了非常热烈的掌声。”   另一位专家Greg Rose如此评价:“我刚刚听了Joux和王小云的报告,王所使用的技术能在任何初始下用2^40次hash运算找出SHA-0的碰撞。她在报告中对四种HASH函数都给出了碰撞,她赢得了长时间的起立喝彩,(这在我印象中还是第一次)。…… 她是当今密码学界的巾帼英雄。……(王小云教授的工作)技术虽然没有公开,但结果是无庸质疑的,这种技术确实存在。…… 我坐在Ron Rivest前面,我听到他评论道:‘我们不得不做很多的重新思考了。’”

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

\ 安 /

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值