A题:
思路:找规律吧,首先假设没有石墩,那么包括左岸在内,青蛙能够落脚的位置就有荷叶数+1(+1是包含左岸),青蛙按序号依次跳到右岸,那么ans=m+1
现在有若干个石墩,给青蛙提供落脚点,令n=1,n=2,n=3……很快就能发现,ans成倍数增长,那么利用二进制的左移(<<)便可以快速得到答案。
代码:

#include <bits/stdc++.h>
using namespace std;
int main()
{
    long long n,m;
    scanf("%lld%lld",&n,&m);
    long long ans=m+1;
    ans<<=n;
    printf("%lld\n",ans);
}

B题:
思路:一开始看到题目还以为是什么神奇的大数。。。。。。
看了几遍没有什么思路,后面来做的。
发现求最大公约数的辗转相除法跟这个递推公式有某种默契。
gcd(FN,FN+1)=gcd(FN-1,FN)
那么就可以得到,最终答案就是gcd(A,B)
所以只需要利用辗转相除法,编写递归函数,就可以得到最终的答案了,答案与N无关
需要注意的是,由于数据比较大,需要开long long,函数的参数列表也要注意用long long
代码:

#include <bits/stdc++.h>
using namespace std;
long long gcd(long long a,long long b)
{
    if(b==0) return a;
    return gcd(b,a%b);
}
int main()
{
    long long a,b,c;
    scanf("%lld%lld%lld",&a,&b,&c);
    long long d=gcd(a,b);
    printf("%lld\n",d);
}

C题:
思路:一个质因数的分解题,判断能分解的数的奇偶性,判定谁胜谁负。
代码:

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    scanf("%d",&n);
    if(n==1)
    {
        printf("Nancy\n");
        return 0;
    }
    int num=0;
    for(int i=2;i<=n;i++)
    {
        while(n%i==0)
        {
            num++;
            n/=i;
        }
    }
    if((num&1)==0)
    {
        printf("Johnson\n");
    }
    else
        printf("Nancy\n");
}

D题:
思路:利用并查集,依次将不属于一个集合中的可能边加入,形成最小生成树,在这之前先按照边权大小排序,贪心优先选择较小的边加入,即可得到最小生成树。
代码:

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN=500500;
int par[MAXN];
int rankk[MAXN];
int n,m;
struct node
{
    int u,v,w;
}edge[MAXN];
void init()
{
    for(int i=1;i<=n;i++)
    {
        par[i]=i;
        rankk[i]=0;
    }
}
int find(int x)
{
    if(x==par[x]) return x;
    else
    {
        return par[x]=find(par[x]);
    }
}
void unite(int u,int v)
{
    int du=find(u);
    int dv=find(v);
    if(du==dv) return;
    if(rankk[du]<rankk[dv])
        par[du]=dv;
    else
    {
        par[dv]=du;
        if(rankk[du]==rankk[dv])
            rankk[du]++;
    }
}
bool cmp(const node &a,const node &b)
{
    return a.w<b.w;
}
int kruskal()
{   
    int res=0;  
    init(); 
    sort(edge+1,edge+1+m,cmp);  
    for(int i=1;i<=m;i++)    
    {       
        if(find(edge[i].u)!=find(edge[i].v))        
        {           
            unite(edge[i].u,edge[i].v);         
            res=res+edge[i].w;      
        }   
    }   
    return res;
}

signed main() 
{
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%lld%lld%lld",&edge[i].u,&edge[i].v,&edge[i].w);
    }
    printf("%lld\n",kruskal());
} 

E题:
思路:只是修改函数部分好像不行,加一个数组进行暴力,纳入一条边的时候把这个区间对应位置的数组值均+1,删除一条边的时候均-1,由于某位置重复出现多次的时候只算一个,所以选择a[i]==1时将ans++,位置从有到无的时候才会-1,所以选择a[i]==0时ans--,比原代码的修改之处就是加了个a[]数组和修改了结构体node的大小比较方式。
代码:

#include <algorithm>
 #include <iostream>
 #include <cstring>
 #include <climits>
 #include <cstdio>
 #include <vector>
 #include <cstdlib>
 #include <ctime>
 #include <cmath>
 #include <queue>
 #include <stack>
 #include <map>
 #include <set>
 #define fi first
 #define lc (x<<1)
 #define se second
 #define U unsigned
 #define rc (x<<1|1)
 #define Re register
 #define LL long long
 #define CLR(i,a) memset(i,a,sizeof(i))
 #define FOR(i,a,b) for(Re int i = a;i <= b;++i)
 #define ROF(i,a,b) for(Re int i = a;i >= b;--i)
 #define SFOR(i,a,b,c) for(Re int i = a;i <= b;i+=c)
 #define SROF(i,a,b,c) for(Re int i = a;i >= b;i-=c)
 #define DEBUG(x) std::cerr << #x << '=' << x << std::endl
 const int MAXN = 1000000+5;
 int N,maxL;
struct node
{
    int l,r;
    bool operator < (const node &other) const
    {
         if(l==other.l)
            return r<other.r;
         return l < other.l;
     }
};
std::set<node> L;
 int a[MAXN];
int ans=0;
 int main(){
     scanf("%d%d",&N,&maxL);
     while(N--){
         int opt,x,y;
         scanf("%d%d%d",&opt,&x,&y);
         if(opt == 1){
             if(L.find((node){x,y}) != L.end()) continue;
             L.insert((node){x,y});
             for(int i=x;i<=y;i++)
             {
                 a[i]++;
                 if(a[i]==1)
                     ans++;
             }
         }
         if(opt == 2){
             if(L.find((node){x,y}) == L.end()) continue;
             L.erase((node){x,y});
             for(int i=x;i<=y;i++)
             {
                 a[i]--;
                 if(a[i]==0)
                     ans--;
             }
         }
         if(opt == 3){
             printf("%d\n",ans);
         }
     }
     return 0;
 }