一些板子

在此记录一些本人百打百挂的板子:

1. 扩展欧几里得(以青蛙的约会为模板)

    题意:给出n,m,x,y,l,求g*l+k*(n-m)=x-y中k的最小正整数解

    做法:明显是扩欧板子虽然我不会写

       注意n-m为负数时,将n-m与x-y同时取相反数即可

              记住x=y1,y=x1-a/b*y1

              当求出ax+by=gcd(a,b)的特解后,通解为y=y0-(a/gcd)*t,x=x0+(b/gcd)*t

              上代码

#include <cstdio>

inline long long int gcd(long long int a,long long int b){return b==0?a:gcd(b,a%b);}

inline void exgcd(long long int a,long long int b,long long int &x,long long int &y){
    if(b==0){
        x=1,y=0;
        return;
    }
    
    long long int x1,y1;
    exgcd(b,a%b,x1,y1);
    x=y1,y=x1-a/b*y1;
    return;
}

int main(void){
    long long int xx,yy,mm,nn,ll;
    scanf("%lld%lld%lld%lld%lld",&xx,&yy,&mm,&nn,&ll);
    
    long long int a=ll,b=mm-nn,c=yy-xx;
    if(b<0)    b=-b,c=-c;
    long long int d=gcd(a,b);
    
    if(c%d){
        printf("Impossible");
        return 0;
    }
    
    else{
        a/=d,b/=d,c/=d;
        
        long long int x,y;
        exgcd(a,b,x,y);
        
        printf("%lld\n",((y*c)%a+a)%a);
    }
}
青蛙的约会

 

 

2. 单调队列(以琪露诺为模板)

     题目描述:(车 万 厨 狂 喜)

        在幻想乡,琪露诺是以笨蛋闻名的冰之妖精。

        某一天,琪露诺又在玩速冻青蛙,就是用冰把青蛙瞬间冻起来。但是这只青蛙比以往的要聪明许多,在琪露诺来

        之前就已经跑到了河的对岸。于是琪露诺决定到河岸去追青蛙。

        小河可以看作一列格子依次编号为0到N,琪露诺只能从编号小的格子移动到编号大的格子。而且琪露诺按照一种

        特殊的方式进行移动,当她在格子i时,她只移动到区间[i+l,i+r]中的任意一格。你问为什么她这么移动,这还不简

        单,因为她是笨蛋啊。

        每一个格子都有一个冰冻指数A[i],编号为0的格子冰冻指数为0。当琪露诺停留在那一格时就可以得到那一格的

        冰冻指数A[i]。琪露诺希望能够在到达对岸时,获取最大的冰冻指数,这样她才能狠狠地教训那只青蛙。

        但是由于她实在是太笨了,所以她决定拜托你帮它决定怎样前进。

        开始时,琪露诺在编号0的格子上,只要她下一步的位置编号大于N就算到达对岸。

   做法:  单调队列模板题之一(还有一个叫滑动窗口的我写了三遍Orz)

        记住一句话-->当一个选手比你小,还比你强,你就可以退役了

        上代码

 1 #include <cstdio>
 2 #include <cstring>
 3 #define int long long int
 4 
 5 int a[300005],dp[300005],last[300005],queue[300005];
 6 int step[300005];
 7 
 8 signed main(void){
 9     memset(dp,-0x3f,sizeof(dp));
10     int n,l,r;
11     scanf("%lld%lld%lld",&n,&l,&r);
12     for(int i=0;i<=n-1;i++)    scanf("%lld",&a[i]);
13     
14     dp[0]=0;
15     int head=1,tail=0;
16     for(int i=l;i<=n+r;i++){
17         while(head<=tail&&dp[i-l]>dp[queue[tail]])    tail--;
18         while(head<=tail&&queue[head]<i-r)            head++;
19         queue[++tail]=i-l;
20         dp[i]=dp[queue[head]]+a[i];
21         last[i]=queue[head];
22     }
23     
24     int maxx_loc,maxx=-99999999999999;
25     for(int i=n+r-1;i>n;i--)    if(dp[i]>=maxx)    maxx_loc=i,maxx=dp[i];
26     
27     int cntt=0;
28     for(int i=maxx_loc;i;i=last[i]){
29         step[++cntt]=i;
30     }
31     printf("%lld\n",maxx);
32     /*printf("0 ");
33     for(int i=cntt;i>1;i--)    printf("%I64d ",step[i]);
34     printf("-1");*/
35 }
琪露诺

 

3. tarjan求强联通分量(以上白泽慧音为模板(((

     题目描述:(车 万 厨 狂 喜 + +)

       在幻想乡,上白泽慧音是以知识渊博闻名的老师。

       春雪异变导致人间之里的很多道路都被大雪堵塞,使有的学生不能顺利地到达慧音所在的村庄。因此慧音决定换一

       个能够聚集最多人数的村庄作为新的教学地点。

       人间之里由N个村庄(编号为1..N)和M条道路组成,道路分为两种一种为单向通行的,一种为双向通行的,分别用

       1和2来标记。如果存在由村庄A到达村庄B的通路,那么我们认为可以从村庄A到达村庄B,记为(A,B)。

       当(A,B)和(B,A)同时满足时,我们认为A,B是绝对连通的,记为<A,B>。绝对连通区域是指一个村庄的集合,在这个

       集合中任意两个村庄X,Y都满足<X,Y>。

       现在你的任务是,找出最大的绝对连通区域,并将这个绝对连通区域的村庄按编号依次输出。若存在两个最大的,

       输出字典序最小的,比如当存在1,3,4和2,5,6这两个最大连通区域时,输出的是1,3,4。

   做法:   tarjan模板题,没啥好说的

         上代码

 1 #include <cstdio>
 2 #include <stack>
 3 #include <vector>
 4 using namespace std;
 5 
 6 stack<int> s;
 7 vector<int> v[50005];
 8 
 9 struct node{
10     int to,next;
11 }e[100005];
12 
13 int tarjan_cnt=0,cnt=0,color_cnt=0;
14 int head[50005],dfn[50005],low[50005],color[50005],color_num[50005];
15 bool vis[50005];
16 
17 inline void add(int from,int to){
18     e[++cnt].to=to;
19     e[cnt].next=head[from];
20     head[from]=cnt;
21 }
22 
23 inline int tarjan(int now){
24     s.push(now);
25     dfn[now]=low[now]=++tarjan_cnt;
26     vis[now]=1;
27     
28     for(int i=head[now];i;i=e[i].next){
29         if(!dfn[e[i].to]){
30             tarjan(e[i].to);
31             low[now]=min(low[now],low[e[i].to]);
32         }
33         else if(vis[e[i].to])    low[now]=min(low[now],dfn[e[i].to]);
34     }
35     
36     if(dfn[now]==low[now]){
37         vis[now]=0;
38         color[now]=++color_cnt;
39         
40         while(1){
41             int noww=s.top();
42             s.pop();
43             vis[noww]=0;
44             color[noww]=color_cnt;
45             color_num[color_cnt]++;
46             if(noww==now)    break;
47         }
48     }
49 }
50 
51 int main(void){
52     int n,m;
53     scanf("%d%d",&n,&m);
54     
55     for(int i=1;i<=m;i++){
56         int from,to,t;
57         scanf("%d%d%d",&from,&to,&t);
58         if(t==2)    add(to,from);
59         add(from,to);
60     }
61     
62     for(int i=1;i<=n;i++)    if(!dfn[i])    tarjan(i);
63     for(int i=1;i<=n;i++)    v[color[i]].push_back(i);
64     
65     int biaoji=0,maxx=0,minn_2=999999999;
66     for(int i=1;i<=color_cnt;i++){
67         if(color_num[i]>maxx)    maxx=color_num[i],biaoji=i,minn_2=v[i][0];
68         else if(color_num[i]==maxx)    if(v[i][0]<minn_2)    biaoji=i;
69     }
70     
71     printf("%d\n",maxx);
72     for(int i=0;i<v[biaoji].size();i++)    printf("%d ",v[biaoji][i]);
73 }
上白泽慧音
posted @ 2019-11-07 13:43  Pride205  阅读(155)  评论(0编辑  收藏  举报