那些年错过的蓝桥杯(三)

来源:互联网 发布:linux查看硬件命令 编辑:程序博客网 时间:2024/05/15 07:50
               **第六届蓝桥杯A组省赛**

饮料换购
乐羊羊饮料厂正在举办一次促销优惠活动。乐羊羊C型饮料,凭3个瓶盖可以再换一瓶C型饮料,并且可以一直循环下去(但不允许暂借或赊账)。

请你计算一下,如果小明不浪费瓶盖,尽量地参加活动,那么,对于他初始买入的n瓶饮料,最后他一共能喝到多少瓶饮料。

输入:一个整数n,表示开始购买的饮料数量(0 < n < 10000)
输出:一个整数,表示实际得到的饮料数

例如:
用户输入:
100
程序应该输出:
149

用户输入:
101
程序应该输出:
151

#include <bits/stdc++.h>using namespace std;int main(){    ifstream infile("in.txt");    int s,n;    infile>>n;    s=n;    while (n>=3) {        s+=n/3;        n=n/3+n%3;    }    cout<<s<<endl;    return 0;}

垒骰子
赌圣atm晚年迷恋上了垒骰子,就是把骰子一个垒在另一个上边,不能歪歪扭扭,要垒成方柱体。
经过长期观察,atm发现了稳定骰子的奥秘:有些数字的面贴着会互相排斥!
我们先来规范一下骰子:1 的对面是 4,2 的对面是 5,3 的对面是 6。
假设有 m 组互斥现象,每组中的那两个数字的面紧贴在一起,骰子就不能稳定的垒起来。
atm想计算一下有多少种不同的可能的垒骰子方式。
两种垒骰子方式相同,当且仅当这两种方式中对应高度的骰子的对应数字的朝向都相同。
由于方案数可能过多,请输出模 10^9 + 7 的结果。
不要小看了 atm 的骰子数量哦~

「输入格式」
第一行两个整数 n m
n表示骰子数目
接下来 m 行,每行两个整数 a b ,表示 a 和 b 数字不能紧贴在一起。

「输出格式」
一行一个数,表示答案模 10^9 + 7 的结果。

「样例输入」
2 1
1 2

「样例输出」
544

「数据范围」
对于 30% 的数据:n <= 5
对于 60% 的数据:n <= 100
对于 100% 的数据:0 < n <= 10^9, m <= 36

#include <bits/stdc++.h>using namespace std;typedef long long ll;const int MO=1e9+7;const int opps[]={0,4,5,6,1,2,3};struct Mat {    int r,c;    ll el[7][7];    Mat() {}    Mat(ll x) {        r=c=6;        memset(el,0,sizeof(el));        for (int i=1;i<=r;i++)  el[i][i]=x;    }    Mat(int _r,int _c,ll x){        r=_r;c=_c;        for (int i=1;i<=r;i++)             for (int j=1;j<=c;j++)  el[i][j]=x;    }    Mat operator *(const Mat &b) {        Mat res(r,b.c,0);        for (int i=1;i<=r;i++)             for (int j=1;j<=b.c;j++)                 for (int k=1;k<=c;k++) res.el[i][j]+=el[i][k]*b.el[k][j];        return res;    }    Mat operator %(const int Mo) {        for (int i=1;i<=r;i++)             for (int j=1;j<=c;j++)                 el[i][j]=el[i][j]%Mo;        return (*this);    }};template <class DataType>DataType fpow(DataType x,int n){    DataType res(1);    while (n) {        if (n&1)  res=x*res%MO;        x=x*x%MO;        n>>=1;    }    return res;}int main(){    ifstream infile("in.txt");    int n,m;    infile>>n>>m;    Mat coop(6,6,1);    for (int i=1;i<=m;i++) {        int x,y;        infile>>x>>y;        coop.el[x][opps[y]]=0;        coop.el[y][opps[x]]=0;    }    coop=fpow(coop,n-1);    ll ans=0,fo=4;      for (int i=1;i<=6;i++)        for(int k=1;k<=6;k++) ans=(ans+coop.el[i][k])%MO;    ans=ans*fpow(fo,n)%MO;    cout<<ans;    return 0;}

灾后重建
Pear市一共有N(<=50000)个居民点,居民点之间有M(<=200000)条双向道路相连。这些居民点两两之间都可以通过双向道路到达。这种情况一直持续到最近,一次严重的地震毁坏了全部M条道路。
震后,Pear打算修复其中一些道路,修理第i条道路需要Pi的时间。不过,Pear并不打算让全部的点连通,而是选择一些标号特殊的点让他们连通。
Pear有Q(<=50000)次询问,每次询问,他会选择所有编号在[l,r]之间,并且 编号 mod K = C 的点,修理一些路使得它们连通。由于所有道路的修理可以同时开工,所以完成修理的时间取决于花费时间最长的一条路,即涉及到的道路中Pi的最大值。

你能帮助Pear计算出每次询问时需要花费的最少时间么?这里询问是独立的,也就是上一个询问里的修理计划并没有付诸行动。

【输入格式】
第一行三个正整数N、M、Q,含义如题面所述。
接下来M行,每行三个正整数Xi、Yi、Pi,表示一条连接Xi和Yi的双向道路,修复需要Pi的时间。可能有自环,可能有重边。1<=Pi<=1000000。
接下来Q行,每行四个正整数Li、Ri、Ki、Ci,表示这次询问的点是[Li,Ri]区间中所有编号Mod Ki=Ci的点。保证参与询问的点至少有两个。

【输出格式】
输出Q行,每行一个正整数表示对应询问的答案。

【样例输入】
7 10 4
1 3 10
2 6 9
4 1 5
3 7 4
3 6 9
1 5 8
2 7 4
3 2 10
1 7 6
7 6 9
1 7 1 0
1 7 3 1
2 5 1 0
3 7 2 1

【样例输出】
9
6
8
8

【数据范围】
对于20%的数据,N,M,Q<=30
对于40%的数据,N,M,Q<=2000
对于100%的数据,N<=50000,M<=2*10^5,Q<=50000. Pi<=10^6.
Li,Ri,Ki均在[1,N]范围内,Ci在[0,对应询问的Ki)范围内。

#include <bits/stdc++.h>#define M 200001#define N 50001using namespace std;struct Node{    int b1,e1,value;};struct Pan{    int max,a,b;    Pan *pa,*pb;};set<int> my[2*M];Pan *pp[N],*head;priority_queue<Node> t;int mark[N],sig[N];int n,m,q,sum=0;bool operator<(Node a,Node b){    return a.value>b.value;}ostream& operator<<(ostream &out,Node &a){    out<<a.b1<<" "       <<a.e1<<" "       <<a.value<<endl;    return out;}int find(int x,int m[]){    if(x==m[x]) return x;    else return find(m[x],m);}void unio(int x,int y,int m[]){    int a,b;    a=find(x,m);    b=find(y,m);    if(a!=b) m[a]=b;}bool check(Node te){     int a=find(te.b1,sig);     int b=find(te.e1,sig);     if(a==b) return false;     unio(a,b,sig);     return true;}void he(int x){     if(pp[x]!=NULL) {        int at=pp[x]->a;        set<int>::iterator it;        for(it=my[at].begin();it!=my[at].end();it++)            my[sum].insert(*it);        at=pp[x]->b;        for(it=my[at].begin();it!=my[at].end();it++)            my[sum].insert(*it);     }}void ptree(Node te){     int a=find(te.b1,mark);     int b=find(te.e1,mark);     Pan *p=(Pan *)malloc(sizeof(Pan));     p->max=te.value;     my[sum].insert(te.b1);     he(a);     p->a=sum;     p->pa=pp[a];     my[++sum].insert(te.e1);     he(b);     p->b=sum++;     p->pb=pp[b];     unio(a,b,mark);     pp[b]=p;     head=p;     //cout<<p->a<<"  "<<p->b<<"********\n";}void print(Pan *p){     if(p==NULL) return;     cout<<p->max<<endl;     set<int>::iterator it;     cout<<"left: ";     for(it=my[p->a].begin();it!=my[p->a].end();it++)         cout<<(*it)<<" ";     cout<<"\nright: ";     for(it=my[p->b].begin();it!=my[p->b].end();it++)         cout<<(*it)<<" ";        cout<<endl;     print(p->pa);     print(p->pb);}int refer(set<int> gg,Pan *p){    set<int>::iterator it;    int t1=0,t2=0;    for(it=gg.begin();it!=gg.end();it++){        if(my[p->a].find(*it)!=my[p->a].end()) t2++;        t1++;        if(t1!=t2&&t2!=0) break;    }    if(t1==t2) return refer(gg,p->pa);    if(t2==0)  return refer(gg,p->pb);    return p->max;}int main(int argc, char *argv[]) {    ifstream infile("in.txt");    int tot=0,a,b,c,d;    struct Node bri;    infile>>n>>m>>q;    for(int i=1;i<=n;i++) {        sig[i]=i;        mark[i]=i;    }    for(int i=0;i<m;i++){         infile>>bri.b1>>bri.e1>>bri.value;        t.push(bri);    }    while(!t.empty()){        bri=t.top();        t.pop();        bool bb=check(bri);        if(bb==false) continue;        tot++;        ptree(bri);        if(tot==m-1) break;    }    //cout<<"tree ok\n";    //print(head);    for(int i=0;i<q;i++){        infile>>a>>b>>c>>d;        int k;        for(k=a;k<=b;k++)            if(k%c==d) break;        set<int> cc;        for(int g=k;g<=b;g+=c)           cc.insert(g);        cout<<refer(cc,head)<<endl;    }    return 0;}

这里写图片描述

坑了宝宝这么久,终于有结果了.
hushanjushi181@sina.com