IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 2022/1/28 -> 正文阅读

[数据结构与算法]2022/1/28

cf?And Matching

应该在推n=8,k=7的时候就该想到这一点了啊,而且k<=n-1,看到这个条件了我愣是没往这个地方想:n-1和其他数与就是其他数,就该抽一下自己发困的脑子,,先看一下8进制的真值表会发现0&n-1,2&n-2...i&n-i-1都是为零的,所以我们再看一下k<=n-2的情况,我们可以把k与上n-1,这样就出来k了,然后与k对应的有一个与他相与为零的数b,n-1也对应着一个,而n-1对应的是0,所以我们可以把n-1和b交换一下位置,这样0和b相与还是为0,而n-1就和k相与为k了;再看k==n-1的时候,我们还可以发现从2开始,2&3,3&4...i&(i+1),都是2的倍数,并且是2,4,6,8这样排列的,知道这个规律我们就可以取2,3,n-4,n-3,你会发现这两组与起来的和是n-2,而那个1,我们要借助0,1,n-2,n-1来实现,0&(n-2),1&(n-1)正好和为1,而2,3,n-4,n-3我们只要把3和n-3的位置换一下就能出来n-2了

#include<bits/stdc++.h>
#define ll long long
typedef __int128 LL;
using namespace std;
const int inf=0x3f3f3f3f;
int t,n,k,a[100005];
int main(){
    //freopen("in.txt","r",stdin);
    cin>>t;
    while(t--){
        cin>>n>>k;
        for(int i=0;i<n;i++) a[i]=i;
        if(n==4&&k==3){
            cout<<-1<<endl;
            continue;
        }
        if(k==n-1){
            swap(a[3],a[n-3]);
            swap(a[n-1],a[n-2]);
        }
        else{
            swap(a[n-1],a[n-k-1]);
        }
        for(int i=0;i<n/2;i++)
        cout<<a[i]<<" "<<a[n-i-1]<<endl;
    }
    return 0;
}

p7076 位运算

自己对位运算太不熟悉了,这道题就是统计出m个条件有那些位是1,然后再看看n个动物的位上是否有m个条件位上的1,有1的该位就变为0就行,最后只要看看条件为上有几个为0,就是2的几次方,最后减个n就可以了,,,,脑子不清晰了,看看博客就明白了

题解 P7076 【动物园(洛谷民间数据)】 - OMG_wc 的博客 - 洛谷博客 (luogu.com.cn)

#include<bits/stdc++.h>
#define ll long long
typedef __int128 LL;
using namespace std;
const int inf=0x3f3f3f3f;
unsigned ll n,m,c,k,p[1000005],q[1000005],a[1000005],bit[66],ori=1ull;
int main(){
    //freopen("in.txt","r",stdin);
    cin>>n>>m>>c>>k;
    for(int i=1;i<=n;i++) cin>>a[i];
    unsigned ll ans=1ull;
    for(int i=1;i<=m;i++){
        cin>>p[i]>>q[i];
        bit[p[i]]=1;
    }
    for(int i=1;i<=n;i++)
        for(int j=0;j<k;j++){
            if(bit[j]==0) continue;
            if((a[i]>>j)&1)
                bit[j]=0;
        }
    for(int i=0;i<k;i++)
        if(!bit[i]) ans<<=1;
    if(n==0&&k==64){cout<<"18446744073709551616"<<endl;return 0;}
    cout<<ans-n<<endl;
    return 0;
}

p7095 二分,优先队列

现根据力量进行排序(因为精神是以力量为前提的),二分也可以,直接贪心也可以,都能算出力量的最小值;然后重点是精神,我曾经用二分也求出了精神,但不对,不能根据力量的顺序来求精神,这样是错误的,,但我们可以在不打破力量顺序的情况下建一个以精神为关键字的排序,模拟一遍穿装备的过程,如果不需要增加力量就可穿上,那我们就把他压进队列,若穿不上就从队列里找出一个精神需求最小加成最大的装备来穿,直到满足力量需求,到最后所有装备都从队列过一遍之后,再不断进行取出精神需求最小加成最大的装备直到队空

P7095 [yLOI2020] 不离 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include<bits/stdc++.h>
#define ll long long
typedef __int128 LL;
using namespace std;
const int inf=0x3f3f3f3f;
ll t,n,mina=0;
struct game{
    ll s,b,c,d;
    bool operator<(const game &a)const{
    if(b==a.b) return d<a.d;
    return b>a.b;
    }
    /*inline bool operator<(const game &x) const {
		return b ^ x.b ? b > x.b : d ^ x.d ? d < x.d : s ^ x.s ? s > x.s : c < x.c;
	}*/
}a[1000005];
bool cmp1(game a,game e){
    if(a.s==e.s) return a.d>e.d;
    return a.s<e.s;
}
/*inline bool cmp1(game x, game y) {
	return x.s ^ y.s ? x.s < y.s : x.c ^ y.c ? x.c > y.c : x.b ^ y.b ? x.b < y.b : x.d > y.d;
}*/
bool check1(ll x){
    for(int i=1;i<=n;i++){
        if(x<a[i].s)return 0;
        x+=a[i].c;
    }
    return 1;
}
int main(){
    //freopen("in.txt","r",stdin);
    cin>>t;
    cin>>n;
    ll max1=0,max2=0;
    for(int i=1;i<=n;i++) cin>>a[i].s>>a[i].b>>a[i].c>>a[i].d,max1=max(max1,a[i].s),max2=max(max2,a[i].b);
    ll l=0,r=max1,mid;
    sort(a+1,a+n+1,cmp1);
    while(l<=r){
        mid=l+r>>1;
        if(check1(mid)) r=mid-1;
        else l=mid+1;
    }
    mina=l;
    ll minb=0,bb=0;
    priority_queue<game> q;
    for(int i=1;i<=n;i++){
        while(mina<a[i].s){
                if(bb<q.top().b) minb+=q.top().b-bb,bb=q.top().b;
                bb+=q.top().d;mina+=q.top().c;q.pop();
            }
        if(mina>=a[i].s) q.push(a[i]);
        if(i==n){
            while(!q.empty()){
                if(bb<q.top().b) minb+=q.top().b-bb,bb=q.top().b;
                bb+=q.top().d;q.pop();
            }
        }
    }
    cout<<l<<" "<<minb<<endl;
    return 0;
}

p7108 逆元,快速幂

没想到我自己竟然推出公式来了,虽然没推出最后求你元的公式。。。这道题难点应该就是逆元别的没了。。。

P7108 【移花接木】题解 - Lillia 的墓碑 - 洛谷博客 (luogu.com.cn)

#include<bits/stdc++.h>
#define ll long long
typedef __int128 LL;
using namespace std;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;

ll qpow(ll a,ll b){
    ll res=1;
    while(b){
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}
ll getinv(ll a,ll mod){return qpow(a,mod-2);}
ll t,a,b,h;
int main(){
    //freopen("in.txt","r",stdin);
    scanf("%lld",&t);
    while(t--){
        scanf("%lld%lld%lld",&a,&b,&h);
        if(b==1){printf("%lld\n",((a-1)*h+a)%mod);}
        else if(a<=b){printf("%lld\n",qpow(b,h)*a%mod);}
        else{printf("%lld\n",((qpow(b,h)-1)*(a-b)%mod*getinv(b-1,mod)%mod+a*qpow(b,h)%mod)%mod);}
    }
    return 0;
}

p7840

首先,题目要求连 n?1?条边,那么每个点的 di??就至少为1?,每连一条边 di??和会增加2,则总和就为 2n?2?,减去每个点的,剩下的di??就为 n?2?。运用贪心思想每次取出di?+1?影响最小的点,统计答案后把它的 di?+1?再加入队列,执行 n?2?这个过程就行了。

P7840 「C.E.L.U-03」重构 - 随便ad 的博客 - 洛谷博客 (luogu.com.cn)

#include<bits/stdc++.h>
#define ll long long
typedef __int128 LL;
using namespace std;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
ll read() {
    ll x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
    while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    return x*f;
}
void write(int x) {
     if(x<0) putchar('-'),x=-x;
     if(x>9) write(x/10);
     putchar(x%10+'0');
}
ll qpow(ll a,ll b){
    ll res=1;
    while(b){
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}
ll getinv(ll a,ll mod){return qpow(a,mod-2);}
ll n;
struct fu{
    ll d,v;
    bool operator<(const fu &a)const{
    return (2*d+1)*v>(2*a.d+1)*a.v;
    }
}a[300005];
bool cmp(ll a,ll b){return a>b;}
priority_queue<fu>q;
int main(){
    //freopen("in.txt","r",stdin);
    n=read();
    ll ans=0;
    for(int i=1;i<=n;i++) a[i].v=read(),a[i].d=1,q.push(a[i]),ans+=a[i].v;

    for(int i=1;i<=n-2;i++){
        fu tmp=q.top();q.pop();
        ans+=(2*tmp.d+1)*tmp.v;
        tmp.d++;
        q.push(tmp);
    }
    cout<<ans<<endl;
    return 0;
}
/*10
5 4 3 2 -2 -3 -4 -5
5 4 3 2 -2 -3 -4 -5*/

p1570 二分

这个题的check函数挺不好想的sigma(vi)/sigma(ci)>=x,变形推导出sigma(vi-x*ci)>=0,然后就可以根据这个对数组排序,然后选前m个,判断他们的和是否大于0

题解 P1570 【KC喝咖啡】 - 浅色调 的博客 - 洛谷博客 (luogu.com.cn)

#include<bits/stdc++.h>
#define ll long long
typedef __int128 LL;
using namespace std;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
ll read() {
    ll x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
    while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    return x*f;
}
void write(int x) {
     if(x<0) putchar('-'),x=-x;
     if(x>9) write(x/10);
     putchar(x%10+'0');
}
ll qpow(ll a,ll b){
    ll res=1;
    while(b){
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}
ll getinv(ll a,ll mod){return qpow(a,mod-2);}
bool cmp(ll a,ll b){return a>b;}
ll n,m;
struct coffe{
    double v,c;double val;
    bool operator<(const coffe &a)const{
    return val>a.val;
    }
}a[210];
bool check(double x){
    for(int i=1;i<=n;i++) a[i].val=a[i].v-x*a[i].c;
    sort(a+1,a+n+1);
    double res=0;
    for(int i=1;i<=m;i++) res+=a[i].val;
    return res>=0;
}
int main(){
    //freopen("in.txt","r",stdin);
    n=read();m=read();
    double l=0,r=0,mid;
    for(int i=1;i<=n;i++) a[i].v=read();
    for(int i=1;i<=n;i++) a[i].c=read(),r=max(r,a[i].v*1.0/a[i].c);
    while(r-l>1e-6){
        mid=(l+r)/2;
        if(check(mid)) l=mid;
        else r=mid;
    }
    printf("%.3f",l);
    return 0;
}
/*10
5 4 3 2 -2 -3 -4 -5
5 4 3 2 -2 -3 -4 -5*/

p2759 log函数

求x位数的方法:lg(x)+1,,证明:

由于m为正整数,必然存在正整数n使得10^(n-1)<=m<10^n,则m的位数为n,对此不等式取对数得n-1<=lg(m)<n,故m的位数为[lg(m)]+1。

这题数据量大,所以用二分降低复杂度

题解 P2759 【奇怪的函数】 - - 洛谷博客 (luogu.com.cn)

#include<bits/stdc++.h>
#define ll long long
typedef __int128 LL;
using namespace std;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
ll read() {
    ll x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
    while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    return x*f;
}
void write(int x) {
     if(x<0) putchar('-'),x=-x;
     if(x>9) write(x/10);
     putchar(x%10+'0');
}
ll qpow(ll a,ll b){
    ll res=1;
    while(b){
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}
ll getinv(ll a,ll mod){return qpow(a,mod-2);}
bool cmp(ll a,ll b){return a>b;}
ll n,l=0,r=2e9,mid;
int main(){
    //freopen("in.txt","r",stdin);
    n=read();
    while(l<r){
        mid=l+r>>1;
        ll len=mid*log10(1.0*mid)+1;
        if(len<n) l=mid+1;
        else r=mid;
        //cout<<l<<" "<<r<<endl;
    }
    cout<<l<<endl;
    return 0;
}
/*10
5 4 3 2 -2 -3 -4 -5
5 4 3 2 -2 -3 -4 -5*/

p2804 逆序对

其实这应该叫做求顺序对。。。求有几段区间的平均数大于m,则先每个a[i]都减去m,则问题转化成了求有几段区间的平均数大于0,而求出前缀和,问题就又变为有几个i,j满足s[j]-s[i-1]>0,即s[j]>s[i-1],这就转化为求顺序对了

题解 P2804 【神秘数字】 - yukimura83 的博客 - 洛谷博客 (luogu.com.cn)

#include<bits/stdc++.h>
#define ll long long
typedef __int128 LL;
using namespace std;
const int inf=0x3f3f3f3f;
const int mod=92084931;
ll read() {
    ll x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
    while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    return x*f;
}
void write(int x) {
     if(x<0) putchar('-'),x=-x;
     if(x>9) write(x/10);
     putchar(x%10+'0');
}
ll qpow(ll a,ll b){
    ll res=1;
    while(b){
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}
ll getinv(ll a,ll mod){return qpow(a,mod-2);}
bool cmp(ll a,ll b){return a>b;}
ll n,m,a[200005],sum[200005],ans=0,b[200005];
void Merge(ll l,ll mid,ll r){
    ll i=l,j=mid+1,t=0;
    while(i<=mid&&j<=r){
        if(sum[i]<sum[j]){
            b[t++]=sum[j++];
            ans=(ans+mid-i+1)%mod;
        }
        else b[t++]=sum[i++];
    }
    while(i<=mid) b[t++]=sum[i++];
    while(j<=r) b[t++]=sum[j++];
    for(i=0;i<t;i++) sum[l+i]=b[i];
}
void Mersort(ll l,ll r){
    if(l<r){
        ll mid=l+r>>1;
        Mersort(l,mid);
        Mersort(mid+1,r);
        Merge(l,mid,r);

    }
}
int main(){
    //freopen("in.txt","r",stdin);
    sum[0]=0;
    n=read();m=read();
    for(int i=1;i<=n;i++){
        a[i]=read();
        a[i]-=m;
        sum[i]=sum[i-1]+a[i];
    }
    Mersort(0,n);
    cout<<ans<<endl;
    return 0;
}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-01-29 23:20:21  更:2022-01-29 23:22:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 17:44:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码