2023/12/11
14周学习笔记
快速幂指算法
再写题之前,学到了取模运算法则
设a,b,c都为非0正数。
1、(a%c+b%c)%c=(a+b)%c
2、(ab)%c=(a%cb%c)%c
快速幂指法主要运用了第二种方法。
设保留最后c位小数
算法思路:例如3^5,若要对其结果取余,我们可以拆为(3 3%c3 3%c3%c)%c,我们可以
先把3%c存起来,然后变为3^2求解,指数为奇数时存下3%c,然后对让指数除二,之后让底数
变为原来两倍,若之后指数满足大于0,则继续进行循环,直到指数除2得0时结束循环。返回she的值。
```c
在这里插入代码片#include<stdio.h>
long long ZPY(long long wo, long long ai)
{
long long she=1;
while(ai>0)
{
if(ai%2==1)
{
she=she*wo%10000;
}
ai=ai/2;
wo=(wo*wo)%10000;
}
return she;
}
int main()
{
int T,i,a,b,sum;
scanf("%d",&T);
for(i=0;i<T;i++)
{
scanf("%d %d",&a,&b);
sum=ZPY(a,b);
printf("%04lld\n",sum);
}
return 0;
}
半分查找法
#include<stdio.h>
int main()
{
int n,i,j,k,number,a[1000],count=0;
scanf("%d %d",&n,&number);
getchar();
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);//输入n组递增的数据
}
int low,high,mid;
low=0,high=n-1;
while(low<=high)
{
mid=(low+high)/2;
if(a[mid]<number)
{
low=mid+1;
}
if(a[mid]>number)
{
high=mid-1;
}
if(a[mid]==number)
{
count++;
break;
}
}
if(count==0)
{
printf("找不到\n");
}
else printf("找到了\n");
return 0;
}
半分查找大大减少了时间复杂度,就是当查找的数据量很大的时候,用循环查找太过麻烦,虽然电脑计算能力很快,逐个循环查找,利用半分查找减少了电脑计算时间,更加方便。
首先定义三个整型数据,low、high、mid,分别为被查找数中的第一位和最后一位,mid就位low和high相加除2了,观察查找值与mid相互比较,若查找值大于mid则让下一次循环时low=mid+1,在比较。若查找值小于mid,则让high=mid-1,以此推理。最后当mid等于查找值时让count加1,结束循环,若一直未找到,直到low大于high时结束循环,输出找不到。
sscanf函数
在这里插入代码片#include<stdio.h>//四则运算
int main()
{
int n,i,j,a,b;
float sum;
char arr[110][30];
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%s",arr[i]);
}
for(i=0;i<n;i++)
{
if(arr[i][0]=='a')
{
sscanf(arr[i],"add(%d,%d)",&a,&b);
printf("%d\n",a+b);
}
if(arr[i][0]=='m')
{
sscanf(arr[i],"mul(%d,%d)",&a,&b);
printf("%d\n",a*b);
}
if(arr[i][0]=='s')
{
sscanf(arr[i],"sub(%d,%d)",&a,&b);
printf("%d\n",a-b);
}
if(arr[i][0]=='d')
{
sscanf(arr[i],"div(%d,%d)",&a,&b);
if(b==0)
{
printf("error\n");
}
else
{
if(a%b==0)
{
printf("%d\n",a/b);
}
else
{
sum=(float)a/b;
printf("%.2f\n",sum);
}
}
}
}
return 0;
}
sscanf函数能读出字符串中所想要的数据,并提出来计算。其用法多样,根据所想要的数据类型可以读出。
欧拉筛法
在这里插入代码片#include<stdio.h>
#include<stdbool.h>
int main()
{
bool decide[1100000];
int a[10000],i,j,count,m;
while(scanf("%d",&m)!=EOF)
{
count=0;
for(i=2; i<=m; i++)
{
decide[i]=true;
}
for(i=2; i<=m; i++)
{
if(decide[i])
{
a[count]=i;
count++;
}
for(j=0; j<count&&a[j]*i<=m+1; j++)
{
decide[a[j]*i]=false;
if(i %a [j]==0)
break;
}
}
for(i=0; i<count; i++)
{
printf("%d\n",a[i]);
}
}
return 0;
}
欧拉筛法时间复杂度为o(n),要求数据量大时可大大节省时间,使用到了bool类型标记质数和合数,核心代码是当i%a[j]==0时结束循环,保证其被最小数相除,不用再循环标记运算了。
前缀和算法
当数据量非常大的时候,我们求多个区间的和时,运用传统思路循环遍历求和时过于繁琐,而且费时间,虽然是计算机。因此我们定义一个数组存放大数据时,再定义一个数组用来存放从数据1到第n个数据和。即用数学公式表达为:b(n)=b(n-1)+a(n),前提b(0)=a(0),b(n)代表了a数组从第一个到n个之和,因此我们计算区间l到m和时,只要用b(m)-b(l)思路,求出区间和,避免了繁琐计算。