OJ 2057
做这题的时候发现我对十六进制的输入输出好像不太了解,然后就去补了一下这方面的知识:
16进制数输入 :
-- %p是输入一个十六进制的数
--scanf("%llx ", &a);也可以输入十六进制并且比较正规
同理16进制输出:
printf("%llX\n", a);也可输出一个十六进制数 (大写X则输出十六进制为大写字母否则小写x输出为小写字母)
OJ2058
The sum problem(http://acm.hdu.edu.cn/showproblem.php?pid=2058)
Problem Description
Given a sequence 1,2,3,......N, your job is to calculate all the possible sub-sequences that the sum of the sub-sequence is M.
Input
Input contains multiple test cases. each case contains two integers N, M( 1 <= N, M <= 1000000000).input ends with N = M = 0.
Output
For each test case, print all the possible sub-sequence that its sum is M.The format is show in the sample below.print a blank line after each test case.
Sample Input
20 10
50 30
0 0
Sample Output
[1,4]
[10,10]
[4,8]
[6,9]
[9,11]
[30,30]
2.一开始看到这题,心想这不是可以直接用循环就能做出来的吗,然后刷刷刷就做出来了,然而提交以后显示Time Limit Exceeded......果然还是太年轻了。
初期代码:
#include<stdio.h>
int main(){
int m ,n;
while(scanf("%d %d",&n,&m)!=EOF){
int i,j,sum;
if(n==0&&m==0)break;
for(i=1;i<=m;i++){
sum=0;j=i;
while(sum<m){
sum+=j;
if(sum==m)break;
j++;
}
if(sum==m)printf("[%d,%d]\n",i,j);
}
}
}
改了好久一直超时,就去讨论区看了下大佬们的想法------“等差数列”
用两个for循环,时间复杂度为n²,数字太大,运行会超时。
所以围绕等差数列求和公式进行:(首项 * 末项)*项数/2.
这里我们用 i(数字i的值) 表示首项, j表示项数, i+j-1得到末项。
所以我们的任务就是要找到 i 和 j的值。
写公式:(i+(i+j-1)) * j / 2 = m
由上式得: i = ((2 * m)/j - j + 1)/2;
为了进一步较少循环的次数:j * j + 2 * i * j - j = 2m; 且i大于等于1;则2 * i * j - j >0;
所以j < sqrt(2 * m);
3.最后代码:
#include <stdio.h>
#include <math.h>
int main()
{
int m, n, i, j, len;
while(scanf("%d%d", &n, &m) && (m+n))
{
len = sqrt(2.0*m);
for(j = len; j >= 1;j --)
{
i = ((2*m)/j-j+1)/2;
if((i+(i+j-1))*j/2 == m)
printf("[%d,%d]\n", i, i+j-1);
}
printf("\n");
}
}