码迷,mamicode.com
首页 > 其他好文 > 详细

10.2考试总结

时间:2018-10-08 16:34:28      阅读:182      评论:0      收藏:0      [点我收藏+]

标签:val   main   dig   必须   ons   简单的   lin   continue   getch   

10.2考试试题

A、同余方程:

Description:

\(给定求的解数\text{给定}l_1,r_1,l_2,r_2,m \text{求}x\in[l_1,r_1],y\in[l_2,r_2],x\text{^}y\equiv 0\pmod{m}的解数\)

\(1<=l_1,l_2,r_1,r_2<=10^{18},1<=m<=10^9\)

Solution:

我们先将区间化为前缀,\([l_1,r_1]\times[l_2,r_2]\)化成\(([0,r_1]-[0,l_1-1])\times([0,r_2]-[0,l_2-1])=[0,r_1]\times[0,r_2]-[0,l_1]\times[0,r_2]-[0,l_2]\times[0,r_1]+[0,l_1]\times[0,l_2]\)

剩下的,我们来考虑前缀怎么办:\([0,a)\times[0,b)的贡献\)
先从简单的来,对于\([0,2^n)\times[0,2^n)\)

\(A\in[0,2^n), B\in[0,2^n)\)

\(A\)任选时,我们存在唯一的\(B\),使\(A\text{^}B=km\)

\(而的值域而A\text{^}B的值域I\subset [0,2^n)\) ,\(所以\)\(我只要计算出I中m的倍数\times 2^n\)

再难一点,对于\([0,2^n)\times (0,2^m)不妨设n<=m\)

\(当任意选时我们存在唯一的使注意反之不同因为当A任意选时,我们存在唯一的B,使A\text{^}B=km,注意反之不同(因为m>=n)\)

\(而的值域我们只要计算出中的的倍数而A\text{^}B的值域I\subset [0,2^n),我们只要计算出I中的m的倍数\times 2^n\)

最后我们在考虑\([0,a)\times[0,b)\)

我们将两个数个数变成二进制,并逐位考虑

\(假如a的倒数第位为1,b的倒数第位为a,不妨设假如a的倒数第n位为1,b的倒数第m位为1,不妨设n<=m\)

\(那么如果将这两位的变成,那么我们后位的后位都可以随便设这个思维像是数位那么如果将这两位的1变成0,那么我们a后n-1位,b的后m-1位,都可以随便设,这个思维像是数位DP\)

那么这个问提可以向上一个问题归纳,类比上问题,得到新的区间\([a-2^{n-1},a),[b-2^{m-1},b)\)

如果将上一行区间进行偏移的话,就可以得到类似上一个问题的区间,\([0,2^{n-1})\times[0,2^{m-1})\)

\([a-2^{n-1},a)\times[b-2^{m-1},b)\) 这样的区间,它的左端点应该是将a的后m位清空(我们可以办到因为m>=n)的值

右端点为左端点\(+2^{m-1}\),值域就是如此,再\(\times 2^{n-1}\)

综上所述,我们解决了这个问题

code:

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const long long mod=998244353;
long long l1,l2,r1,r2,M;
inline long long cal(long long a,long long b){
    long long ans=0;
    for(long long i=0;i<=60;++i)
        for(long long j=0;j<=60;++j){
            if( ( a & ( 1ll << i ) ) && ( b & ( 1ll << j ) ) ){
                long long n=min(i,j);
                long long m=max(i,j);
                long long w=(1ll<<n)%mod;
                long long l=((a-(1ll<<i))^(b-(1ll<<j)))&(~((1ll<<m)-1ll));//与下同
                //long long l=((a-(1ll<<i)&(~((1ll<<m)-1ll)))^(b-(1ll<<j)))&(~((1ll<<m)-1ll));
                long long r=l+(1ll<<m)-1ll;
                long long num=(r/M-l/M+((l%M)==0))%mod;
                ans=(ans+num*w)%mod;
            }
        }
    return ans;
}
int main(){
    cin>>l1>>r1>>l2>>r2>>M; 
    cout<<(cal(r1+1,r2+1)-cal(l1,r2+1)-cal(l2,r1+1)+cal(l1,l2)+mod)%mod;
    return 0;
}

B、旅游:

给定一张无向图,第\(i\)条边的边权为\(2^i\),从1号点出发,要求每条边至少走一遍,并回到1号,求最小代价

无向图欧拉回路的判定:每个点的度数为偶数。

如果所有的点度数为偶数,那时我们只用把所有的边加一遍即可,依靠这个思路,我们可以加上一些边使所有点的度数为偶数,因为所有边的边权为2的幂,所以我们增加的边一定是在MST上。

所以我们可以在最小生成树上递推:如果我们的叶子的度数为奇数,我们必须将叶子到他的父亲的边加1,根据这个,我们可以推到根节点。注意根节点没有父亲,所以他不能调整,但实际上因为任意一张无向图所有点的度数之和为偶数,不可能出现只有一个根节点为奇数的情况

code:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cctype>
using namespace std;
const int mod=998244353;
const int MAXX=500010; 
int n,m,e[MAXX],deg[MAXX];
int head[MAXX],ver[MAXX<<1],nxt[MAXX<<1],edge[MAXX<<1];
int f[MAXX];
int tot,ans;
inline int find(int x){
    if(f[x]==x)return x;
    else return f[x]=find(f[x]);
}
inline int read(){
    int x=0;bool f=0;
    char c=getchar();
    while(!isdigit(c)){
        if(c==‘-‘)f=1;
        c=getchar();
    }
    while(isdigit(c)){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return f?-x:x;
}
inline void add(int x,int y,int z){
    ver[++tot]=y;
    nxt[tot]=head[x];
    head[x]=tot;
    edge[tot]=z;
}
inline void dfs(int x,int fa,int val){
    for(int i=head[x];i;i=nxt[i]){
        int y=ver[i];
        if(y==fa)continue;
        dfs(y,x,edge[i]);
    }
    if(deg[x]&1){
        deg[x]++;
        deg[fa]++;
        ans=(ans+val)%mod;
    }
}
int main(){
    freopen("B.in","r",stdin);
    freopen("B.out","w",stdout);
    n=read();m=read();
    for(int i=1;i<=n;++i)f[i]=i;
    int temp=2;
    for(int i=1;i<=m;++i){
        e[i]=temp;
        temp=temp*2%mod;
        ans=(ans+e[i])%mod;
    }
    for(int i=1;i<=m;++i){
        int x,y;
        x=read();y=read();
        deg[x]++;deg[y]++;
        int fu=find(x);
        int fv=find(y);
        if(fu==fv)continue;
        f[fu]=fv;
        add(x,y,e[i]);
        add(y,x,e[i]);
    }
    dfs(1,0,0);
    printf("%d\n",ans);
    return 0;
}

10.2考试总结

标签:val   main   dig   必须   ons   简单的   lin   continue   getch   

原文地址:https://www.cnblogs.com/ARTlover/p/9755044.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!