2010年清华大学计算机研究生机试真题

本文解析了三道特殊算法题目:特殊乘法、整数拆分及求root(N,k)。通过详细阐述解题思路和提供代码实现,帮助读者理解算法背后的逻辑与技巧。

题目1083:特殊乘法

题目描述:

写个算法,对2个小于1000000000的输入,求结果。

特殊乘法举例:123 * 45 = 1*4 +1*5 +2*4 +2*5 +3*4+3*5

输入:

 两个小于1000000000的数

输出:

 输入可能有多组数据,对于每一组数据,输出Input中的两个数按照题目要求的方法进行运算后得到的结果。

样例输入:
123 45
样例输出:
54
#include<iostream>
using namespace std;
long long a,b;
int x[20];
int y[20];
void solve()
{
    int i=0;
    int j=0;
    int xn=0;
    int yn=0;
    while(a)
    {
        x[i++]=a%10;
        a/=10;
    }
    xn=i;
    i=0;
    while(b)
    {
        y[i++]=b%10;
        b/=10;
    }
    yn=i;
    long long sum=0;
    for(i=0;i<xn;++i)
        for(j=0;j<yn;++j)
        {
            sum+=x[i]*y[j];
        }
    cout<<sum<<endl;
}
int main()
{
    while(cin>>a>>b)
    {
        solve();
    }
    return 0;
}

题目1084:整数拆分

题目描述:

一个整数总可以拆分为2的幂的和,例如:
7=1+2+4
7=1+2+2+2
7=1+1+1+4
7=1+1+1+2+2
7=1+1+1+1+1+2
7=1+1+1+1+1+1+1
总共有六种不同的拆分方式。
再比如:4可以拆分成:4 = 4,4 = 1 + 1 + 1 + 1,4 = 2 + 2,4=1+1+2。
用f(n)表示n的不同拆分的种数,例如f(7)=6.
要求编写程序,读入n(不超过1000000),输出f(n)%1000000000。

输入:

每组输入包括一个整数:N(1<=N<=1000000)。

输出:

对于每组数据,输出f(n)%1000000000。

样例输入:
7
样例输出:
6

采用奇偶讨论:

当 n=2k+1时候,只是在n=2k的种类的基础上每次加个1而已,种类数和n=2k相同。当n=2k的时候,如果拆分出1,则和n=2k-1的时候种类数一样,如果不拆分出1,不包含1意味着分解因子中最小为2,各项除以2,则和n=k的时候种类数一样所以 

f(2k+1)=f(2k)   f(2k)=f(2k-1)+f(k)
注意:(a+b)%m == (a%m+b%m)%m

#include<iostream>
using namespace std;
int a[1000001];
int main() 
{
	int n;
	while(cin>>n)
	{
		a[1]=1;
		for(int i=2;i<=n;i++) 
		{
			if(i%2!=0)
				a[i]=a[i-1];
			else
				a[i]=(a[i-1]+a[i/2])%1000000000;
		}
		cout<<a[n]<<endl;
		
	}
	return 0;
}

题目1085:求root(N, k)

题目描述:

    N<k时,root(N,k) = N,否则,root(N,k) = root(N',k)。N'为N的k进制表示的各位数字之和。输入x,y,k,输出root(x^y,k)的值 (这里^为乘方,不是异或),2=<k<=16,0<x,y<2000000000,有一半的测试点里 x^y 会溢出int的范围(>=2000000000) 

输入:

    每组测试数据包括一行,x(0<x<2000000000), y(0<y<2000000000), k(2<=k<=16)

输出:

    输入可能有多组数据,对于每一组数据,root(x^y, k)的值

样例输入:
4 4 10
样例输出:
4
算法分析:采用直接模拟的方式,先计算X^Y,然后在进制转换,但是大数据(x^y)将超出范围。

数学公式推导:


由上述分析,我们希望找到Nr=N%(k-1)。

当Nr等于0时,处于边界条件,Nr=k-1。Nr就是我们要求得的结果。

#include<iostream>
using namespace std;
long long sum;
long long ans,ans1;
long long x,y,k;
long long quickmod(long long a,long long b,long long k) //计算(a^b)modk   
{    
    long long count = 1;    
    while(b)//用一个循环从右到左遍历b的所有二进制位    
    {    
        if(b&1)//这是按二进制表示进行“与”运算的;判断此时b[i]的二进制位是否为1     
            count = (count*a)%k;//乘到结果上,这里a是a^(2^i)%k    
        b/=2;  //b的所有二进制向右平移一位   
        a = (a*a)%k;    
    }    
    return count;    
}  
int main()
{
	while(cin>>x>>y>>k)
	{
		ans=quickmod(x,y,k-1);
		if(ans==0)
			ans=k-1;
		cout<<ans<<endl;
	} 
	return 0;
}













评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值