首页 > 其他分享 >SCU预备役Day 1

SCU预备役Day 1

时间:2023-07-28 23:13:27浏览次数:30  
标签:y2 int mid x2 y1 数组 SCU 预备役 Day

2023-07-28 22:13:56

 基本算法

二分与三分

使用范围:答案具有单调性时。

原理:判断远比求解简单

定义域:

  1. 为整数域的时候,若区间长度为N,则需要进行log2N次运算
  2. 为实域的时候,判断R-L精度是否达到要求,需要R-L>=eps(但因为实数运算带来的精度问题,若eps太小会导致是循环,往往指定二分次数更好)

整数域:

 1 while(l<r){
 2     int mid=(l+r)>>1;
 3     if(check(mid)) r=mid;
 4     else l=mid+1;
 5     return l;
 6 }
 7 
 8 while(l<r){
 9     int mid=(l+r+1)>>1;
10     if(check(mid)) l=mid;
11     else r=mid-1;
12     return l;
13 }
14 
15 while(l<=r){
16     int mid=(l+r)>>1;
17     if(check(mid)) ans=mid,l=mid+1;
18     else r=mid-1;
19 }

实数域:

while(fabs(l-r)>dlt){
    mid=(l+r)/2.0;
    if(check(mid)) r=mid;
    else l=mid;
}

还有一种方法:如果指定二分次数为t,那么结束时区间长度为L/pow(2,t),根据这个值是否符合我们的精度就可以了。

 

 三分模板

使用范围:求凸性函数的极值问题(单峰函数)

 

#include<bits/stdc++.h>
using namespace std;
int n;
double l,r,a,b,c,d;
double s[20];
double ans(double x){
    double sum=0,t=1.0;
    for(int i=1;i<=n;i++){
        t*=x;
        sum+=s[i]*t;
    }
    return sum;
}
bool check(double m1,double m2){
    if(ans(m1)>ans(m2)) return true;
    else return false;
}
int main(){
    cin>>n>>l>>r;
    for(int i=1;i<=n;i++){
        cin>>s[n-i+1];
    }
    int k;
    cin>>k;
    while(fabs(l-r)>=0.00001){
        double m1=l+(r-l)/3.0,m2=r-(r-l)/3.0;
        if(check(m1,m2)) r=m2;
        else l=m1;
    }
    cout<<(l+r)/2.0<<endl;
    return 0;
}

 

前缀和与差分:

典例1:求L - R 区间的和  

Sum[r]-Sum[l]

二维情况:

复杂度:O(nm)

Sum[a][b]=sum[a-1][b]+sum[a][b-1]-sum[a-1][b-1]+x[a][b];

如果求(x1,y1)到(x2,y2)的矩阵和的话就是s[x2,y2]-s[x1-1,y2]-s[x2,y1-1]+s[x1-1,y1-1];

 

 

类似于数学中的求导和积分,差分可以看成前缀和的逆运算。

差分数组:

首先给定一个原数组a:a[1], a[2], a[3],,,,,, a[n];

然后我们构造一个数组b : b[1], b[2], b[3],,,,,, b[i];

使得 a[i] = b[1] + b[2] + b[3] + ,,,,,, + b[i]

也就是说,a数组是b数组的前缀和数组,反过来我们把b数组叫做a数组的差分数组。 换句话说,每一个a[i]都是b数组中从头开始的一段区间和。

何构造差分b数组:

a[0 ]= 0;

b[1] = a[1] - a[0];

b[2] = a[2] - a[1];

........

b[n] = a[n] - a[n - 1];

运用:m个操作,将区间[l,r]的数都加上c,最后输出区间数组。

我们知道a数组是b的前缀和,那么b[l]+c会影响l之后的a数组,最后我们再打个补丁:b[r+1]-c。

 

 

 

二维差分

  构造公式:b[i][j]=a[i][j]-a[i-1][j]-a[i][j]+a[i-1][j-1];

 

void insert(int x1,int y1,int x2,int y2,int c)
{     //对b数组执行插入操作,等价于对a数组中的(x1,y1)到(x2,y2)之间的元素都加上了c
    b[x1][y1] += c;
    b[x2 + 1][y1] -= c;
    b[x1][y2 + 1] -= c;
    b[x2 + 1][y2 + 1] += c;
}

 

位运算

运算符优先情况

 

常见技巧

 

 

 

^(异或运算的运算法则)

  1. a ^ b = b ^ a
  2. a ^ b ^ c = a ^ (b ^ c) = (a ^ b) ^ c;
  3. d = a ^ b ^ c 可以推出 a = d ^ b ^ c.
  4. a ^ b ^ a = b.

 

 

问题定义:有2n+1个数,只有一个单着,别的都是成对的,找出这个单着的数。比如:2 1 3 2 1。
答:异或计算,一趟搞定。时间复杂度o(n),答案为3,因为两个相同的数异或为0.

 

问题:1-1000放在含有1001个元素的数组中,只有唯一的一个元素值重复,其它均只出现一次。每个数组元素只能访问一次,设计一个算法,将它找出来;不用辅助存储空间,能否设计一个算法实现?

 

解答:
令,1^2^…^1000(序列中不包含n)的结果为T
则1^2^…^1000(序列中包含n)的结果就是T^n。
T^(T^n)=n。
所以,将所有的数全部异或,得到的结果与1^2^3^…^1000的结果进行异或,得到的结果就是重复数。

问题: 在一堆数中,有且仅有两种数,出现了奇数次,而其他种的数,都出现了偶数次,请找出出现了奇数次的这两种数。

 

 

int main()
{  
    int a=0,b=0;//设出现奇数次的数为a,b
    int t=0,i;
    int rightone;//二进制下,从右往左的第一个1
    int arr[20];

    for( i=0;i<20;i++)
    {
        t^=arr[i];
    }
    //现在的t==a^b,这两个出现奇数次的数异或

    //因为t==a^b;
    //a!=b
    //所以t的二进制肯定有一位上是1
    rightone=t&(~t+1);
    //一个数与(&)上自己取反+1的数,结果得到这个数二进制下最右侧的1
    //并且我们知道,a和b两者在这一位上,只有一者位上是1,另一个一定是0.
    for(i=0;i<20;i++)
    {
        if(t^arr[i]==0)//将该最右位是1和0的区分开
        {
            a^=arr[i];//此时a等于一种奇数次数^一些出现过偶数次数且该位也是1的数
                      //而出现偶数次可以抵消,所以直接得到了第一个出现了奇数次的数
        }
    }
    b=t^a;//由此再得到b
}

 

 

 

Bitset的使用

Bitset<N>

 

 

 

 

今日好题

 

发现这个数列只与前两个数有关,假设弄成二维,前四项为(1,0),(0,1),(1,1),(1,2)可以发现对于单独的x方向和y方向又分别构成了斐波拉契数列且xi=fib(i-2),yi=fib(i-1)。

另一个重点是 fib(30)约等于8e5,远远超过了本体范围,那么我们只需要预处理30位的fib即可。

最终问题转化成ax+by=n的二元一次方程问题(易错的是y>=n)

 

 

思路:

首先可以肯定的是需要用到前缀和的思想,但是最后发现遍历s数组的时候复杂度n2会TLE。

解决关键:同余定理

当是s[i]和s[j]%k之后若余数相同则s[i+1]到s[j]为所求

最后我们用桶排序处理答案

 

正宗的斐波拉契数列

 

标签:y2,int,mid,x2,y1,数组,SCU,预备役,Day
From: https://www.cnblogs.com/patrick-star-/p/17589036.html

相关文章

  • Day2
    数组专题:leetcode:977暴力解法也是最开始就可以想到的方法:defsortedSquares(self,nums):""":typenums:List[int]:rtype:List[int]"""foriinrange(len(nums)):nums[i]*=nums[i]......
  • day16
    一.白哥的鸽子1.得到一张jpg,binwalk显示格式有问题,010打开,在末尾发现类似flag的数据2.是栅栏密码,字数为3时,得到flag二.split_all1.得到一张无法显示的png,删去png的头,补上gif文件头2.现象出来的图像很窄,与之前的一个题很像,扔进Stegsolve中,看不到,查看framebrowser,发现有770......
  • [代码随想录]Day03-链表part01
    题目:203.移除链表元素思路:做链表首先最好有个虚拟头指针,这样做删除添加操作的时候可以统一操作否则还得特判。那删除元素的过程,从虚拟头指针开始要做以下几步:如果当前p的next不为空,那么就可以进行判断如果p的next的值是val(↑p的next不为空↑),那么就把p的next修改为p的下......
  • 济南 Day 5 图论
    SolutionT1emoairx的二叉树原题链接4114:emoairx的二叉树简要思路一道简单的递归签到题,每次找到较大的数进行除以\(2\),每次递归把步数加一,直到两个点走到同一个点上。完整代码#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;intm;intans(intx......
  • Python基础day55
    通过结合前端页面实现ORM对数据的增删改查写一个页面,把数据库中的数据以表格形式展示出来,然后在每一行的后面加上两个按钮,分别是修改、删除思路:思考修改功能的逻辑:1.确定修改哪条记录,怎么确定?通过主键id确定唯一一条记录2.点击修改的按钮,需要跳转到一个修改的......
  • 集训Day 5
    A题:  B题: 这是集训以来感觉最好的一次,比赛开始,先看了一眼A题问题不大,直接联想到了前缀和,由于这里是异或,就将原来的求[l,r]区间内和的公式:sum[r]-sum[l-1]改为sum[r]^sum[l-1](根据的是异或的自反性)直接A掉(get100pt),继续看B题,B题由于我基本没做对过,就只是看了几眼,写了一......
  • openEuler TechDay——熊博带你玩转欧拉
    openEuler是什么?是打破惯性的技术突破?是倾力合作的生态共建?还是踏浪前行的商业反哺?**openEulerTechDay本期邀请到了欧拉技术委员会熊伟博士,以对话的方式为大家答疑解惑,全方位立体剖析欧拉发展。**熊博将带你走入开源世界,透视欧拉最新进展,分享开源社区合作,探讨未来商业发展。多少欧......
  • Day5
    Day5模拟赛T1设\(dp_{i,j,k,0/1}\)表示走到第\(i,j\)个格子,前面异或和为\(k\)的方案数\(0/1\)表示前面的每个路径丢了\(/\)没丢转移方程:\(f_{i,j,k,0}=f_{i-1,j,a_{i,j}\oplusk,0}+f_{i,j-1,a_{i,j}\oplusk,0}+f_{i-1,j,k,1}+f_{i,j-1,k,1}\)......
  • 鸟哥Linux私房菜学习记录day4
    第九章vim程序编辑器简易执行范例替换 :n1,n2s/word1/word2/g   :1,$s/word1/word2/g(c)(确认)删除:x向后删除一个字符,X向前删除一个字符,nx向后连续删n个字符(n)dd删除(剪切)光标所在的那一行nyy复制光标所在的那n行nG:移动到第n行u恢复前一个操作ctrl+r重做上一个动作.......
  • DAY6
    指针练习声明变量:pstr是一个指向数组的指针,该数组内含20个char类型的值char(*pstr)[20];编写一个函数,返回储存在int类型中数组中的最大值,并在一个简单的程序中测试该函数#include<stdio.h>intget_max(intnumber[],intn){intmax=number[0];inti;......