計蒜客 2020藍橋杯模擬賽第一場補題


一:B組藍橋杯

A:有趣的數字

題意:
1到 1e5 中質數中包含5這個數字的質數個數

#include<bits/stdc++.h>

using namespace std;
bool pf(int n)
{
    for(int i=2;i<=n/i+1;i++)
    {
        if(n%i==0)
            return false;
    }
    int  m=n;
    while(m)
    {
        if(m%10==5)return true;
        m/=10;
    }
    return false;
}
int main ()
{
    int num=0;
    for(int i=3;i<100000;i++)
    {
        if(pf(i))
        {
            cout<<i<<endl;
         num++;
        }
    }
    cout<<num<<endl;
    return 0;
}

答案:3282

B:爬樓梯

題意:每次只能爬1,2,3,4個台階,一共十個台階,第五個和第七個台階不能使用,到達第十個台階的方法種類數。

#include<iostream>

//簡單遞推題:就這幾個手推就行 代碼純屬糊弄
using namespace std;
int f[20];
int main ()
{
    //最多能走四步則第一個台階有一種情況,第二個台階有1+第一個台階的情況,第三個台階有 1+第一個台階情況+第二個台階情況;
    f[0]=0;
    f[1]=1;
    f[2]=2;//1+1
    f[3]=4;//1+2+1
    f[4]=8;//1+2+4+1
    f[5]=0;//1+2+4+1

    for(int i=6;i<=10;i++)
    {
        if(i==7)continue;
        else f[i]=f[i-1]+f[i-2]+f[i-3]+f[i-4];
    }
    cout<<f[10];
    return 0;
}

答案:72

把那個f[4]算成了7 傻狗一個

C:七巧板

題意:

這個圖中加五條直線分割成最多多少個區域。

 

 

emmm 我還以為是從一個空的三角形中畫直線,那個 規律也很好找,每個直線盡量切割最多個區域即可,因為一條直線只能將一個區域分割成兩個。

emm:再重復一遍 不管是空三角形還是里邊有填充的三角形 都是計算下一條直線放到哪里能切割最多區域:下下條似乎是++,依次類推

這道題

 

 

 第一條橙色直線 切6個區域,增加六個區域,下一條紫色直線切7個區域,增加7個區域,依次大膽類推

7+6+7+8+9+10=47 √

答案:47

然后我大膽類推  :空三角形 :1+1+2+3+4+5=16 hhhh(*^_^*)

把空三角形看作是一個平面來處理 似乎是這樣子:

 轉一個不錯的博客如下:

直線/折線/圓/三角形划分平面&直線切割球問題大總結(最多能划分多少區域)

 D:蘋果

 

題意:balabla cf改的 差不多意思

 從左往右依次拿,盡量導致最后剩余的蘋果更接近0,當下只考慮當前的一個達到最小,3個3個拿到最少之后,與后兩個拼湊拿,一直到不能再小再往右遍歷

#include<bits/stdc++.h>

using namespace std;
int a[(int)1e3];
int main ()
{
    int n;
    cin.tie(0);
    cin>>n;
    for(int i=0;i<n;i++)
    {
       cin>>a[i];
    }
    int num=0;
    for(int i=0;i<n;i++)
    {
        num+=a[i]/3;
        if(a[i]>=3)
            a[i]%=3;
        if(i<=n-3)
        {
            int mi=min(min(a[i],a[i+1]),a[i+2]);
            num+=mi;
            a[i]-=mi;
            a[i+1]-=mi;
            a[i+2]-=mi;
        }
    }
    cout<<num<<endl;
    return 0;
}

 

 

 

 

 答案:62

 

 E:方陣

題意:再n*n的方陣中,當A和B之間的連線上沒有點為A和B可以互相見到,問有多少對這樣的AheB 洛谷原題

#include<iostream>

using namespace std;
int gcd(int a,int b){return b==0 ?a:gcd(b,a%b);}
long long dist(int a,int b){return a*a+b*b;}
int main ()
{
    long long num=0;
    long long e=1e9+7;
    int  n;
    long k;
    cin>>n>>k;
    k*=k;
    for(int i=1;i<n;i++)
        for(int j=1;j<n;j++)
    {
        if(gcd(i,j)==1&&dist(i,j)<=k)
            num=(num+(n-j)*(n-i)%e)%e;
    }
    num*=2;
    num+=(2*n*(n-1)%e);
    cout<<num<<endl;
    return 0;
}

 

 

 

 

 

 大體這么個意思 至於怎么化簡那個式子 去洛谷看看

 

 

 

F:尋找重復項

題意:有一個數列 \{a_n\}{an},a_0=1a0=1,a_{i+1} =(A\times a_i+a_i \mod B)\mod Cai+1=(A×ai+aimodB)modC,請你編程求出這個數列第一次出現重復的項的標號。如果答案超過 20000002000000 輸出 "-1"(不加引號)

#include<iostream>
#include<unordered_map>
using namespace std;
unordered_map<long long,int> p;
int main ()
{
    long long  num=1;
    long long A,B,C;
    cin>>A>>B>>C;
    p[1]=1;
    bool f=true;
    for(int i=1;i<=(int)2e6;i++)
    {
        num=(num*A+ num%B)%C;
        //cout<<num<<endl;
        if(p.count(num))
        {
            f=false;
            cout<<i<<endl;
            break;
        }
        else
            p[num]=1;
    }
    if(f)cout<<-1<<endl;

    return 0;
}

考察 unordered_map或者hash_map 標記

C++ 11標准中加入了unordered系列的容器。unordered_map記錄元素的hash值,根據hash值判斷元素是否相同。map相當於java中的TreeMap,unordered_map相當於HashMap。無論從查找、插入上來說,unordered_map的效率都優於hash_map,更優於map;而空間復雜度方面,hash_map最低,unordered_map次之,map最大。

對於STL里的map容器,count方法與find方法,都可以用來判斷一個key是否出現,count統計的是key出現的次數,因此只能為0/1,而find基於迭代器實現,以mp.end()判斷是否找到要求的key。

//摘抄:https://www.cnblogs.com/zzyoucan/p/9127660.html

I 最短路

題意:求1到所有點的距離和所有點回到1的距離最小值

#include<bits/stdc++.h>

using namespace std;
typedef long long LL;
const int N=20005,M=60005;
LL sum=0;
struct
{
    int x,y;
    LL z;
}a[M];
LL head[N],ver[M],Next[M],edge[M],d[N];
bool v[N];
int n,m,tot;
priority_queue<pair<LL,int>>p;
void add(int x,int y,LL z)
{
    ver[++tot]=y,edge[tot]=z,Next[tot]=head[x],head[x]=tot;
}
void init()
{
    tot=0;
    memset(head,0,sizeof(head));
    memset(ver,0,sizeof(ver));
    memset(Next,0,sizeof(Next));
    memset(edge,0,sizeof(edge));
}

void dijkstra()
{
    memset(d,0x3f,sizeof(d));
    memset(v,0,sizeof(v));
    p.push(make_pair(0,1));
    d[1]=0;
    while(p.size())
    {
        int x=p.top().second;
        p.pop();//找到當前權值最小的x,o(long n),用x進行更新
        if(v[x])continue;
        v[x]=1;
        for(int i=head[x];i;i=Next[i])
        {
            LL y=ver[i],z=edge[i];
            if(d[y]>d[x]+z)
            {
                d[y]=d[x]+z;
                p.push(make_pair(-d[y],y));
            }
        }
    }
}

int main ()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(false);
    int t;
    cin>>t;
    while(t--)
    {
        init();
      cin>>n>>m;
      for(int i=0;i<m;i++)
      {
          cin>>a[i].x>>a[i].y>>a[i].z;
          add(a[i].x,a[i].y,a[i].z);
      }
      dijkstra();
    for(int i=1;i<=n;i++)
       sum+=d[i];
    init();
    for(int i=0;i<m;i++)
    {
        add(a[i].y,a[i].x,a[i].z);
    }
    dijkstra();
    for(int i=1;i<=n;i++)
        sum+=d[i];
    cout<<sum<<endl;
    sum=0;
    }
    return 0;
}

從1開始跑一次單源最短路,求得1到所有點的權值。

重新建立鄰接表,將所有有向路徑反向,再跑一次單源最短路,這樣求出的1到所有點的最短路就等效於所有點到1的最短路。

結構體儲存路徑 為了第二次跑最短路

鄰接表儲存  小根堆優化dijkstra

或者用spfa跑兩遍

#include<bits/stdc++.h>

using namespace std;
typedef long long LL;
const int N=20005,M=60005;
LL sum=0;
struct
{
    int x,y;
    LL z;
}a[M];
LL head[N],ver[M],Next[M],edge[M],d[N];
bool v[N];
int n,m,tot;
queue<int>p;
void add(int x,int y,LL z)
{
    ver[++tot]=y,edge[tot]=z,Next[tot]=head[x],head[x]=tot;
}
void init()
{
    tot=0;
    memset(head,0,sizeof(head));
    memset(ver,0,sizeof(ver));
    memset(Next,0,sizeof(Next));
    memset(edge,0,sizeof(edge));
}

void spafa()
{
    memset(d,0x3f,sizeof(d));
    memset(v,0,sizeof(v));
    d[1]=0;
    p.push(1);
    while(p.size())
    {
        int x=p.front();
        p.pop();
        v[x]=0;
        for(int i=head[x];i;i=Next[i])
        {
            LL y=ver[i],z=edge[i];
            if(d[y]>d[x]+z)
            {
                d[y]=d[x]+z;
                if(!v[y])p.push(y);
            }
        }
    }
}

int main ()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(false);
    int t;
    cin>>t;
    while(t--)
    {
        init();
      cin>>n>>m;
      for(int i=0;i<m;i++)
      {
          cin>>a[i].x>>a[i].y>>a[i].z;
          add(a[i].x,a[i].y,a[i].z);
      }
      spafa();
    for(int i=1;i<=n;i++)
       sum+=d[i];
    init();
    for(int i=0;i<m;i++)
    {
        add(a[i].y,a[i].x,a[i].z);
    }
   spafa();
    for(int i=1;i<=n;i++)
        sum+=d[i];
    cout<<sum<<endl;
    sum=0;
    }
    return 0;
}

區別不大:(spfa沒使用小根堆優化)

 

 上邊是spfa 下邊是 dijkstra


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM