1.取余处理;
真的服,一道题环绕我好久,真无语。
#include<stdio.h>
#define mol (int)(1e9+7)
int a[2030000] = { 1,2 };
int main() {
int t, n;
scanf("%d", &t);
for (long long i = 2; i <= 200000; i++)
a[i] = (a[i - 1]%mol + a[i - 2]%mol + (i * (i+1)/ 2) % mol) % mol;
while (t--)
{
scanf("%d", &n);
printf("%d\n", a[n-1]);
}
return 0;
}
这里面最大的坑,有两个,一个是i从0开始所以我的函数应该是i*(i+1);而不是i*(i-1);
真的无语,还有一个就是i的类型,因为i最大为200000,所以i*i可能会超出数据类型最大值,所以要设立long long型,这是最大的坑,又是数据类型的,踩了好多次了,哎,这题真是烦了好久!
2.插入排序
题目:
#include <stdio.h>
int main() {
void sort(int a[], int k);
int T, n, a[1000], k;
scanf("%d", &T);
while (T--)
{
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf("%d", &a[i]);
scanf("%d", &k);
sort(a, k);
for (int i = 0; i < n; i++)
printf("%d ", a[i]);
}
return 0;
}
void sort(int a[], int k)
{
int i = 0, j = 0, t;
for (i = 1; i <= k; i++)
{
t = a[i];
j = i - 1;
while (j >= 0 && a[j] > t) {
a[j+1] = a[j];
j--;
}
a[j + 1] = t;
}
}
这里的k代表这第k趟排序,如果k=n-1时便能全部排好,详情http://t.csdnimg.cn/oPj6J
3.二分法
这个数据太大,要超时,所以用二分法;(这里的数是排好序的)
二分查找运用于排好序中,找某个数,因为这堆数很多,就容易超时,就运用二分法;
#include <stdio.h>
#define maxn (int)1e6
int a[maxn];
int main() {
int n;
int left,k, right,m,taget,mid;
scanf("%d%d", &n,&m);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
while (m--) {
k = -1;
scanf("%d", &taget);
left = 1; right = n ;
while (left < right) {
mid = (left + right) / 2;
if (a[mid] >= taget)right = mid;
else if (a[mid] < taget)left = mid + 1;
}
if (a[left] == taget)
printf("%d ", left);
else printf("-1 ");
}
return 0;
}
总结:感觉思维被固化了,题目改变了点点就感觉迷迷糊糊的;
二分法主要是找一个数,所以后面跳出while循环也是要left等于right时,那么最终就只能是一个值,
这里找的时最左边的元素,那么我们可以用左闭区间右边开区间来进行二分法;
模板一:
while (l < r)
{
int mid = (r + l) / 2;
if (a[mid >= taget])r = mid; //这里用了闭区间,并且这里的r没有加1;注意,这里相当于一直往靠,因为当区间内的数相同
//时这里一直时右边界在移动。
else l = mid + 1; //这里的a[mid]一定是不等于taget的所以要加个一
}
相反:如果想往有边界靠;
模板二:
这里就是if(a[mid] <= taget)l = mid;
else if (a[mid] > taget)r = mid - 1;
4.前缀和差分(一维,二维)
题目:
解题:
int n, p, i, min;
int a[1005000], d[1005000];
#include<stdio.h>
int main() {
scanf("%d%d", &n, &p);
for (i = 1; i <= n; i++)
{ //一维的差分;这里a[0]为0;所以d【0】=a【0】;以至于后面可以通过求前缀和算该数字;
scanf("%d", &a[i]); //这样很可能就是中间改变一些值能快速的求出区间和;
d[i] = a[i] - a[i - 1];
}
while (p--) {
int r, l, z;
scanf("%d%d%d", &r, &l, &z);
d[r] += z;
d[l+1] -= z;
}
for (i = 1; i <= n; i++)
d[i] += d[i - 1];
min = d[1];
for (i = 1; i <= n; i++)
if (d[i] < min)min = d[i];
printf("%d", min);
return 0;
}
二维差分,前缀和:
解题:
#include <stdio.h>
#define N 10000
int d[N][N];
int sum[1000][1000];
//void Sert(int x1, int y1, int x2, int y2)
//{
// d[x1][y1] += 1;
// d[x2 + 1][y1] -= 1;
// d[x1][y2 + 1] -= 1;
// d[x2 + 1][y2 + 1] += 1;
//}
//原数组就可以用这个函数输入,当x1,x2相等还有y1和y2相等时这里相当于输入输入原数组,并且这样这样可以直接把
//void type(int a[N][N], int sum[N][N]) //前缀和数组,这里可以把d[][]传入a[][]那末这个前缀和就是原数组
//{
// for (int i = 1; i <= N; i++)
// {
// for (int j = 1; j <= N; j++) {
// sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][i - 1] + a[i][j];
// }
// }
//}
void type1(int x1, int y1, int x2, int y2, int c) //全局定义这个差分数组
{
d[x1][y1] += c;
d[x2+1][y1] -= c;
d[x1][y2 + 1] -= c;
d[x2+1][y2+1] += c;
}
int main() {
int n, m;
scanf("%d%d", &n, &m);
int x1, y1, x2, y2;
/*for(int i=1;i<=n;i++)
for (int j = 1; j <= n; j++) {
scanf("%d", &a[i][j]);
type1(i, j, i, j, a[i][j]);}
这里可以进行算初始差分;
*/
for (int i = 1; i <= m; i++)
{
scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
type1(x1, y1, x2, y2, 1);
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
sum[i][j] = d[i][j] - sum[i - 1][j - 1] + sum[i][j - 1] + sum[i - 1][j];
printf("%d ", sum[i][j]);
}
printf("\n");
}
return 0;
}
差分就是该位置与前一个位置的差,那么差分的前缀和就是原数组,运用前缀和可以快速算出区间和(区间的值改变后),因为改变后要循环改值会需要很多时间,运用这个前缀和可以快速算区间和,而差分和前缀和一起运用起来,就可以快速改变(进行多次增减值)值,
二维数组
差分模板:
这里很容易错,注意模板的+1;
5.快速排序
void quicksort(int a[], int L,int R)
{
if (L >= R)return;
int left = L, right = R;
int key = a[left];
while (left < right) {
while (a[right] >= key && left < right)right--;
a[left] = a[right];
while (a[left] <= key && left < right)left++;
a[right] = a[left];
if (left >= right)a[left] = key;
}
quicksort(a, L, right - 1);
quicksort(a, right+1, R);
}
找一个key,通常找数列左边第一个,两边的区间left和right不断缩进,小于key在左边,大于key在右边;时间复杂度nlogN;
这周还行,一般般,但是浮躁了一些,希望下周要沉淀下来,可怕的感冒快快离去