note:善于计算时间复杂度
0 | 1 |
---|---|
枚举法 | 分类枚举、暴力 |
求最大公因数 | 辗转相除>发散->最小公倍数 |
记忆化思想 | 预处理、前缀和思想 |
指出斐波那契数列和辗转相除法的相关性,大致分析一下辗转相除法的时间复杂度
用记忆化思想优化以下程序
#include
using namespace std;
int fib(int n)
{
if (n==0 || n==1) return 1;
int ans=fib(n-2)+fib(n-1);
return ans;
}
int main()
{
int n;
scanf("%d",&n);
printf("%d\n",fib(n));
return 0;
}
===========================我是分割线=============================
**
思路:求出相邻两数的最小公倍数,再与第三个数求最小公倍数,如此反复直到结束
#include
#include
#include
using namespace std;
int gcd(int a,int b);
int main()
{
int n,m;
scanf("%d",&n);
while(n--)
{
int a[100];
int i;
scanf("%d",&m);
for(i=0;iscanf("%d",&a[i]);
for(i=1;i1])*a[i-1];//**最小公倍数=两数乘积/最大公约数**(用到这个公式是难点),储存在a[i]
}
printf("%d\n",a[i-1]);
}
return 0;
}
int gcd(int a,int b) //辗转相除法求最大公约数
{
if(a//判定可不要,一轮之后始终会a>b
swap(a,b);
while(b!=0)
{
int t;
t=a;
a=b;
b=t%b;
}
if(b==0)
return a;
}
===========================我是分割线=============================
思路:回想10进制转成2进制,除以2取余除以2取余…倒过来输出,一样的道理
#include
int main()
{
int n,r,a[1000];
while(scanf("%d %d",&n,&r)!=EOF)
{
int i,j;
int tag=1;
if(n<0) //若是负数,先取其相反数,否则余数全是负数
{
n=(-1)*n;
tag=0;
}
for(i=0;n!=0;i++) //把余数存进数组
{
a[i]=n%r;
n/=r;
}
if(tag==0)
printf("-"); //负数前面先输出-
for(j=i-1;j>=0;j--) //倒序输出
{
if(a[j]>=10)
{
switch(a[j])
{
case 10:printf("A");break; //超过或等于十,换成16进制那样输出,也可以用'A'+i
case 11:printf("B");break;
case 12:printf("C");break;
case 13:printf("D");break;
case 14:printf("E");break;
case 15:printf("F");break;
default:break;
}
continue;
}
printf("%d",a[j]);
}
printf("\n");
}
return 0;
}
===========================我是分割线=============================
这题没什么好说的了…只怪眼瞎把正数看成正整数WA个不停233
#include
int main()
{
int i,n;
scanf("%d",&n);
for(i=0;idouble a,b,c;
scanf("%lf%lf%lf",&a,&b,&c);
if(a+b>c&&a+c>b&&b+c>a&&a&&b&&c)
printf("YES\n"); //**有时题目(下面E题)会叫输出“Yes”,注意别被坑!**
else
printf("NO\n");
}
return 0;
===========================我是分割线=============================
**
note:反复多次读入一个字符型%c会出错
#include
#include
#include
int main()
{
int gao;
char hua,str[10];
int test=0;
while(1)
{
scanf("%s",str); //一开始这里用了%c,结果输出来的图案之前多了很多莫名的空行,输出样例越多,空行越多。**用字符串读入,取它第一个字符可以避免莫名的错误!**
hua=str[0];
if(hua=='@')
return 0;
else
if (test) printf("\n"); //**这个判定很重要**输入@结束后不再换行,其他情况输入后空行再输出结果
test++;
scanf("%d",&gao);
int i,j,k;
for(i=0;iif(i==gao-1)
{
for(k=0;k<2*gao-1;k++)
printf("%c",hua);
printf("\n");
}
else
{
for(j=0;j1;j++)
printf(" ");
printf("%c",hua);
if(i==0)
{
printf("\n");
continue;
}
for(j=0;j<2*i-1;j++)
printf(" ");
printf("%c\n",hua);
}
}
//fflush(stdin); //网上的judge没有键盘缓存,没有意义,
}
return 0;
}
===========================我是分割线=============================
note:多多留意题目叫你输出什么!YES?!Yes?!yes?!
#include
int main()
{
int a,b,i;
while(scanf("%d%d",&a,&b)&&(a||b))
{
int tag=0;
for(i=-10000;i<10000;i++)
if((a-i)*i==b)
{
printf("Yes\n");
tag=1;
break;
}
if(tag==0)
{
printf("No\n");
}
}
return 0;
}
F题没A出来…TAT…
===========================我是分割线=============================
思路:函数判断漂亮数->定义数组表示从1到i的漂亮数总数->记忆化思想->指定区间
#include
#include
#include
#include
#include
using namespace std;
int Isbeauty(int x);
int main()
{
int n,sum[100001]={0};//储存前i个数的和
scanf("%d",&n);
for(int i=1;i<=100000;i++) //**i从1开始**
{
sum[i]=sum[i-1]+Isbeauty(i); **//记忆化思想,优化时间复杂度,否则每次都要1到十万算很可能超时**
}
while(n--)
{
int l,r;
scanf("%d %d",&l,&r);
printf("%d\n",sum[r]-sum[l-1]); //[l,r]闭区间
}
return 0;
}
int Isbeauty(int x) //判定是否漂亮数
{
int a[11]={0};
while(x!=0)
{
if(a[x%10]) //之前出现过一次
return 0; //返回0,不是漂亮数
else
a[x%10]++;
x/=10;
}
return 1; //没出现过重复,返回1,是漂亮数
}
有点忙不过来啊,当天的练习没及时整理…开个好头,祝自己在ACM路上越来越强~