比赛链接:这里

目录

  • OP
  • A 串
    • 思路
    • 代码
  • B 括号
    • 思路
    • 代码
  • C 红和蓝
    • 思路
    • 代码
  • D 点一成零
    • 思路
    • 代码
  • E 三棱锥之刻
    • 思路
    • 代码
  • F 对答案一时爽
    • 思路
    • 代码
  • H 幂塔个位数的计算
    • 思路
    • 代码
  • I 限制不互素对的排列
    • 思路
    • 代码
  • J 一群小青蛙呱蹦呱蹦呱
    • 思路
    • 代码
  • ED

OP

个人能力有限,有的题目实在知识点欠缺太多,可以参照一下其他大佬的全题解。
&感谢ph大佬的全程指导。

A 串

递推。

思路

我们可以先算出长度为 1,2,…,n 的合法串的数量,再进行累加。

介于数据量(2 < n <= 106),通过排列组合来求几乎不可能,单纯打表可能就需要几十分钟。

接下来就是具体的递推过程:

假设长度为 n 的合法字符串有 An 个。长度为 n + 1 的字符串中的前 n 项可以分为两种情况:合法的与非法的。

——对于前 n 项为合法字符串的 n + 1 长字符串,显然情况有 An * 26 种(即第 n + 1 项可以为任意字母);
——对于前 n 项为非法字符串的 n + 1 长字符串,只有前 n 项存在 u 的字符串可以变为合法串,所以含 u 的 n 长字符串的数量为 26n - 25n 个,其中有 An 个合法串,所以此种情况的 n + 1 长合法串有 26n - 25n - An 个(即存在 u 的 n 长非法字符串数量为 含 u 的 n 长字符串数量 减去 合法的 n 长字符串数量,该种串后接 s 即变为合法串)。

所以得到递推公式 An+1 = 25 * An + 26n - 25n

代码

#include <bits/stdc++.h>
using namespace std;
const long long MOD = 1e9 + 7;
long long qs(long long a,long long t)//快速幂取模
{long long ans=1;while(t){if(t&1)ans=ans*a%MOD;a=a*a%MOD;t>>=1;}return ans%MOD;
}
int main()
{long long a=1,i,j,n,ans=1;cin>>n;for(i=3;i<=n;i++){a=a*25+qs(26,i-1)-qs(25,i-1);a%=MOD;if(a<0)a+=MOD;ans+=a;//累加ans%=MOD;}printf("%lld",ans);return 0;
}

B 括号

此题为特判题(Special Judge)

思路

首先我们观察样例,即可得知总括号对数为 每一个左括号后面的右括号总数的累加和。

所以说,为使总字符量尽可能少,我们需要把 k 先粗略地拆成 l1 * r1 的形式( l1 * r1 <= k ), l1 与 r1 需要尽可能接近(均值不等式);

我们可以取 l1 = ⌊ sqrt( k ) ⌋,则 r1 = ⌊ k / l1 ⌋,此时还需要补上差值 d = k - l1 * r1

接下来就是构造了:我们可以依次输出 l1 个左括号,r1 - d 个右括号,1 个左括号,d 个右括号。此时总对数则为 l1 * r1 + d 。

要求是非空串,注意对 0 特判。

代码

#include <bits/stdc++.h>
using namespace std;int main()
{int k,l,r,d,i;scanf("%d",&k);if(k==0){printf("(");return 0;}l=(int)sqrt(k);r=k/l;d=k-r*l;for(i=1;i<=l;i++)printf("(");for(i=1;i<=r-d;i++)printf(")");printf("(");for(i=1;i<=d;i++)printf(")");return 0;
}

比赛时使用的另一种方法,即把 k 拆成 n1 * a12 + n1 * a12 + … 的形式,再构造输出,代码如下,可ac,仅做参考。

#include <bits/stdc++.h>
using namespace std;int main()
{int k,i,ma,j;scanf("%d",&k);if(k==0){printf("(");return 0;}int a[31623]={0};ma=(int)sqrt(k);while(k){a[(int)sqrt(k)]++;k-=(int)sqrt(k)*(int)sqrt(k);}for(i=1;i<=ma;i++){printf("(");if(a[i]){for(j=1;j<=i*a[i];j++)printf(")");}}return 0;
}

C 红和蓝

dfs,涂色

思路

使用两遍bfs,第一遍进行分组和可行性判定,第二遍进行染色

具体实现上(也可以使用链表存图):

第一次dfs时,先递归处理下级节点,再将其与上级节点分入同一组,同时完成可行性判定;

第二次dfs时,判断其与上级节点是否在同一组,在即涂与上级相同的颜色,不在即将自己涂成与上级不同的颜色;

代码

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
struct node{int to, next;
}edge[N];
int head[N], cnt;//cnt为道路数组序号
int mrk[N], col[N], num;//num计组数
bool flag;void add(int u, int v)
{edge[++cnt] = {v, head[u]};//标记前向标head[u] = cnt;//更新待标记前向标
}void dfs1(int u, int fa)
{int son = 0;for(int i = head[u]; i != -1; i = edge[i].next){int v = edge[i].to;if(v != fa){son++;dfs1(v, u);}}if(son == 0 || mrk[u] == 0)//叶节点与未被下级节点涂色的节点需被涂色{if(mrk[fa] != 0)//如果其上级节点已被涂色{flag = 0;return ;}mrk[u] = mrk[fa] = ++num;//此节点与上级节点标成同一数字}
}void dfs2(int u, int fa)
{for(int i = head[u]; i != -1; i = edge[i].next){int v = edge[i].to;if(v == fa) continue;if(mrk[v] == mrk[u])//同组即同色col[v] = col[u];else col[v] = !col[u];//异组即异色dfs2(v, u);}
}int main()
{int n;cin >> n;memset(head, -1, sizeof(head));for(int i = 1; i < n; i++){int u, v;scanf("%d%d",&u,&v);add(u, v);add(v, u);}flag = true;dfs1(1, 0);if(flag == false || mrk[0] != 0)//后者是填色溢出{printf("-1");return 0;}dfs2(1, 0);for(int i = 1; i <= n; i++){printf("%c",(col[i] == 0)?'R':'B');}return 0;
}

D 点一成零

bfs,并查集

思路

假设图中共有p组连通块,每一块包含 c i c_i ci​格,则总方案数即为 p ! ∗ ∏ i = 1 p c i p!*\prod_{i=1}^{p}c_i p!∗∏i=1p​ci​;

那么我们需要做的便是求出p与 c i c_i ci​;

我们可以用遍历网格进行bfs创建并查集,并用并查集维护更改;

最开始抱有侥幸心理,我想对于每一次更改,遍历所有连通块以重新计算ans,结果爆了TLE;

对于具体的维护过程:
如果新增了一个面积为c的连通块,则 a n s = a n s ∗ ( p + 1 ) ∗ c ans=ans*(p+1)*c ans=ans∗(p+1)∗c;
进一步地,如果一个面积为b的连通块,由于方块更新,并入了一个面积为a的连通块,则对这两个连通块来说(即不包括点的那个块,不过该块同理,面积为1) a n s = a n s / p / a / b ∗ ( a + b ) ans=ans/p/a/b*(a+b) ans=ans/p/a/b∗(a+b);逆元处理除法即可;

使并查集的根为连通块中 i ∗ n + j i*n+j i∗n+j最小的点

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll M=1e9+7,N=502;pair<int ,int> fa[502][502];//father
map<pair<int,int>,int>cnt;//以[i][j]为根的并查集所代表的连通块的面积
queue<pair<int,int> >que;//bfs队列
int di[]={0,0,1,-1},dj[]={1,-1,0,0};
int mp[502][502],n,m,cou=0;ll qm(ll a,ll b)//快速幂
{ll ans=1;for(;b;b>>=1){if(b&1)ans=ans*a%M;a=a*a%M;}return ans;
}pair<int,int> find(pair<int,int> pi)//并查集find
{if(fa[pi.first][pi.second]!=pi)fa[pi.first][pi.second]=find(fa[pi.first][pi.second]);return fa[pi.first][pi.second];
}void bfs(pair<int,int> fat)
{int k;while(!que.empty()){pair<int,int>now=que.front();que.pop();for(k=0;k<4;k++){int in=now.first+di[k],jn=now.second+dj[k];if(in>=0&&in<n&&jn>=0&&jn<n&&mp[in][jn]&&fa[in][jn]==make_pair(in,jn)&&!(in==fat.first&&jn==fat.second)){cnt[fat]++;fa[in][jn]=fat;que.push({in,jn});//printf("*%d\n",cnt[fat]);}}}
}int main()
{int i,j,k;string g;cin>>n;for(i=0;i<n;i++){cin>>g;for(j=0;j<n;j++)mp[i][j]=g[j]-'0',fa[i][j]={i,j};}//图接收完毕ll ans=1;for(i=0;i<n;i++)for(j=0;j<n;j++)if(mp[i][j]&&fa[i][j]==make_pair(i,j)){cou++;cnt[{i,j}]=1;que.push({i,j});bfs({i,j});ans*=(ll)cou*cnt[{i,j}];//计算初始ansans%=M;}cin>>m;while(m--){int ci,cj;scanf("%d%d",&ci,&cj);if(mp[ci][cj])printf("%lld\n",ans);//如果本来就是1,则图无任何变化else{mp[ci][cj]=1;//假定其为单独块cnt[{ci,cj}]=1;cou++;ans*=cou;ans%=M;//其作为单独块,更新ans,后面再修正pair<int,int> to={ci,cj};for(k=0;k<4;k++)//判断该及块四周的连通块形成的新连通块的根{int in=ci+di[k],jn=cj+dj[k];if(in>=0&&in<n&&jn>=0&&jn<n&&mp[in][jn]){pair<int,int>fan=find({in,jn});if(fan.first*n+fan.second<to.first*n+to.second)to=fan;}}if(make_pair(ci,cj)!=to)//如果新块的根不是自身,将自身并入新块根所在旧块{pair<int,int>fan=find({ci,cj});fa[fan.first][fan.second]=to;ans*=qm((ll)cou*(cnt[to]*cnt[fan])%M,M-2);cou--;ans%=M;cnt[to]+=cnt[fan];ans*=cnt[to];ans%=M;}for(k=0;k<4;k++){int in=ci+di[k],jn=cj+dj[k];if(in>=0&&in<n&&jn>=0&&jn<n&&mp[in][jn]){pair<int,int>fan=find({in,jn});if(fan!=to)//把除新块根所在旧块以外的旧块并入新块根{fa[fan.first][fan.second]=to;ans*=qm((ll)cou*(cnt[to]*cnt[fan])%M,M-2);cou--;ans%=M;cnt[to]+=cnt[fan];ans*=cnt[to];ans%=M;}}}printf("%lld\n",ans);}}return 0;
}

E 三棱锥之刻

立体几何

思路

设中心点距面距离 ds ,距棱距离 da ,距顶点距离 dp ,喷漆半径 r
分为四种情况:

① r < ds
此种情况即无法喷到漆,面积为 0 ;

② ds <= r <= da
此种情况即每面被喷漆形状均为完整的圆,通过勾股定理求漆面半径,求圆面积即可;

③ da < r < dp
此种情况即为每面被喷漆形状为(三)弦切圆,如下图:

我将其分为三个三角形和一个扇形求面积,因为图中 k l 的长度均可求,便可使用 arccos 求出角度,进而得知扇形所占圆心角,进而求出扇形面积;

④ r >= dp
此时正四面体的四个面均被涂满,求三角形面积即可。

以下数据可参考,图源百度词条正四面体

代码

#include <bits/stdc++.h>
using namespace std;
#define PI acos(-1)int main()
{double r,a,d;cin>>a>>d;if(d*d-a*a/24<0) {printf("0");return 0;}//1r=sqrt(d*d-a*a/24);if(r<=a/2/sqrt(3))printf("%.5lf",4*PI*r*r);//2else if(r>a/2/sqrt(3)&&r<a/sqrt(3))//3{printf("%.5lf",(3*(sqrt(r*r-a*a/12)*a/2/sqrt(3))+PI*r*r*(2*PI-6*acos(a/2/sqrt(3)/r))/(2*PI))*4);}else printf("%.5lf",a*a*sqrt(3));//4return 0;
}

F 对答案一时爽

贪心

思路

最小值当然是 0 ,最大值即为两人答题总数 - 答案相异数。

假设一人全对,此时即为最大值。

代码

#include <bits/stdc++.h>
using namespace std;int main()
{int n,sa=0,i,c=0;char a[202],b[202],g;cin>>n;getchar();c=0;while(c!=n){g=getchar();if(g>='A'&&g<='Z')a[c++]=g;}getchar();c=0;while(c!=n){g=getchar();if(g>='A'&&g<='Z')b[c++]=g;}for(i=0; i<n;i++)if(a[i]==b[i])sa++;printf("%d %d",sa+n,0);return 0;
}

字符串处理一团糟…

H 幂塔个位数的计算

找规律

思路

具体推倒过程过于繁琐,主要是通过 a % 10 a\%10 a%10的结果推倒 a a % 10 a^{a}\%10 aa%10的结果,再进行迭代。
结果会在大概三层之内收束到定值。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
char a[100005],n[100005];
int main()
{scanf("%s%s",a,n);ll la=strlen(a),ln=strlen(n);if(ln==1 && n[0]=='1'){printf("%d\n",a[la-1]-'0');return 0;}else{int a1=a[la-1]-'0';int b=((a[la-2]-'0')*10+a[la-1]-'0')%4;if(a1==0 || a1==1 || a1==5 || a1==6 || a1==9){printf("%d\n",a1);}else if(a1==4){printf("6\n");}else if(a1==2 || a1==8){if(ln==1 && n[0]=='2' && b!=0){printf("4\n");}else{printf("6\n");}}else if(a1==3){if(b==1){printf("3\n");}else{printf("7\n");}}else if(a1==7){if(b==1){printf("7\n");}else if(b==3){printf("3\n");}}return 0;}
}

I 限制不互素对的排列

构造

思路

要用 [ 1 , n ] 的 n 个数构造出含 k ( k <= n / 2 ) 对非互质数对的数列,首先我们想到的就是用偶数构造所求部分,然后顺序排列其他数。

接下来除法默认向下取整

具体来说,对于某偶数 2 * i ,一定与 2 * ( i + 1 ) 不互质;对于某奇数 2 * i + 1 ,一定与 2 * ( i + 1 ) + 1 互质;对于 >= 2 的正整数 i ,一定与 i + 1 互质。

依照以上三条性质,如果输入值为 8 3 我们便可以构造出 [ 2 , 4 , 6 , 8 , 1 , 3 , 5 , 7 ] 与此同时,便发现了一个问题:对于前 n 个数,含有 ⌊ n / 2 ⌋ 个偶数,最多构成 ⌊ n / 2 ⌋ - 1 个偶数对,但是 k <= n / 2 。

解决此种问题,我们可以进一步处理,选择满足以下性质的某偶数:可以表示为 2 * ( 2 * i + 1 ) ,即可以拆成 2 和某奇数的积。将此偶数放在偶数部分末尾,后再接该奇数,则可保证有 k 对非互质数对。

对于该偶数,10,14,18,…,34,…,122,… 均满足条件,但是满足条件的最小数是 6 。取最小数除了方便处理之外,同时也方便可行判定。

此时,本题的输入便有三种情况:

① n < 6 && k = n / 2
此时无可行解,输出 -1;

② n > 6 && k < n / 2
此时输出前 k + 1 个偶数后,其余数依次输出即可;

③ n > 6 && k = n / 2
此时输出除 6 外的前 k - 1 个偶数后,输出 6 3 ,再依次输出其余数。

代码

#include <bits/stdc++.h>
using namespace std;int main()
{int n,k,i;cin>>n>>k;if(n<6&&k==n/2)printf("-1");//1else if(k==n/2)//3{for(i=1;i<=n/2;i++)if(i!=3)printf("%d ",2*i);printf("6 3 1 ");for(i=5;i<=n;i+=2)printf("%d ",i);}else//2{for(i=1;i<=k+1;i++)printf("%d ",2*i);for(i=1;i<=n;i++){if(i%2==0&&i/2<=k+1)continue;printf("%d ",i);}}return 0;
}

J 一群小青蛙呱蹦呱蹦呱

思路

我们手动模拟可知,剩下的数是质因子个数大于等于二的数,也就是说,剩下的数均可表示为 p1^m1 * p2^m2 * … * pn^mn ( n >= 2 )。如下图

对于范围内的所有质数 p[ i ] ,第 j 个剩下的数可以表示为 p1^m1j * p2^m2j * … * pn^mnj 则所有剩下的数的最小公倍数则为 p1^max( m11 , m12 , m13, … , m1j ) * p2^max( m21 , m22 , m23, … , m2j ) * … * pn^max( mn1 , mn2 , mn3, … , mnj) 。
接下来我们的任务就是求出 max() 。

对于 >= 2 的任意 p[ i ] ,小于 N (范围)且 含有 p[ i ] 幂次最大的 剩余数显然是 2 * p[ i ]^m ,则可以求出 m = logp[i]n/2;

对于质数 2 ,最大数则是 3 * 2m ,此时 m = log2n/3 。

之后累乘 p[ i ]m 即可。

代码

#include <bits/stdc++.h>
using namespace std;
const long long MOD = 1e9 + 7;
const long long N=80000007;
long long qs(long long a,long long t)//快速幂取模
{long long ans=1;while(t){if(t&1)ans=ans*a%MOD;a=a*a%MOD;t>>=1;}return ans%MOD;
}
static int p[N];
static bool n[N];int main()
{n[0]=1,n[1]=1;int i,j,c=0;for(i=2;i<=N;i++)//线性筛{if(!n[i])p[c++]=i;for(j=0;j<c&&i*p[j]<=N;j++){n[i*p[j]]=1;if(i%p[j]==0)break;}}int n;//与前面的数组名重复了,但是编译运行没有问题,可能不太好理解cin>>n;if(n<6){printf("empty");return 0;}long long ans=qs(2,(long long)log2(n/3.0));//对2for(i=1;p[i]<=n/2&&i<c;i++)//对其他{ans%=MOD;ans*=qs(p[i],(long long)(log2(n/2.0)/log2(p[i]*1.0)));//浮点除法&换底公式}printf("%lld",ans%MOD);return 0;
}

附:关于线性筛的优化,可以参照这里,(代码未体现)

ED

《 基 础 选 手 》

2021牛客寒假算法基础集训营1(A B C D E F H I J)相关推荐

  1. 2021牛客寒假算法基础集训营1 J 一群小青蛙呱蹦呱蹦呱

    今天的比赛没打( 睡午觉去了,今天太累了 晚上来看看题 2021牛客寒假算法基础集训营1 J 一群小青蛙呱蹦呱蹦呱 题目传送门 板子题( 我们知道由唯一分解定理得,若 n=p1α1×p2α2×p3α3 ...

  2. 【解题报告】2021牛客寒假算法基础集训营4

    [解题报告]2021牛客寒假算法基础集训营4 前面的话 A :九峰与签到题 | 模拟 (签到题) B: 武辰延的字符串 | exKMP D :温澈滢的狗狗 | 二分 E: 九峰与子序列 | d p d ...

  3. 2021牛客寒假算法基础集训营1

    2021牛客寒假算法基础集训营1 A. 串(线性DP) B. 括号(构造) E.三棱锥之刻(几何) F. 对答案一时爽(签到) I. 限制不互素对的排列(构造) J. 一群小青蛙呱蹦呱蹦呱 A. 串( ...

  4. 2021牛客寒假算法基础集训营2 D.牛牛与整除分块

    2021牛客寒假算法基础集训营2 D.牛牛与整除分块 题目链接 题目描述 整除分块,又称数论分块.是数论算法中的重要技巧,你可以在各种需要枚举因子的连续求和类问题中见到它的身影.如杜教筛,莫比乌斯反演 ...

  5. 2021牛客寒假算法基础集训营5 B.比武招亲(上)

    2021牛客寒假算法基础集训营5 B.比武招亲(上) 题目链接 题目描述 众所周知,天姐姐只喜欢天下最聪明的人,为了找到这样的人,她决定比武招亲! 只见天姐姐在榜上留下了这样一道问题,谁做出来了就可以 ...

  6. 2021牛客寒假算法基础集训营4

    九峰与签到题 链接:https://ac.nowcoder.com/acm/contest/9984/A 来源:牛客网 题目描述 九峰正在准备一场毒瘤比赛,他是如此毒瘤以致于他想方设法降低通过率,他认 ...

  7. 2021牛客寒假算法基础集训营5 比武招亲(上)(组合数)

    链接:https://ac.nowcoder.com/acm/contest/9985/B 来源:牛客网 题目描述 众所周知,天姐姐只喜欢天下最聪明的人,为了找到这样的人,她决定比武招亲! 只见天姐姐 ...

  8. 2021牛客寒假算法基础集训营3,签到题DGHIJ

    D. Happy New Year!模拟 #include<bits/stdc++.h> using namespace std; int main(){ios::sync_with_st ...

  9. 2021牛客寒假算法基础集训营6 J.天空之城

    J.天空之城 题目链接:https://ac.nowcoder.com/acm/contest/9986/J 题目描述: 天空之城有5个小镇,名字分别为Ada, Aed, Akk, Orz, Apq, ...

  10. 2021牛客寒假算法基础集训营1 题解

    A.串 题解: dp 三维dp可能更好理解一些. dp[i][j][k]dp[i][j][k]dp[i][j][k]代表长度为iii的字符串,当j=1时代表已经含有u了的字符串的个数,k=1时代表已经 ...

最新文章

  1. LeetCode简单题之逐步求和得到正数的最小值
  2. HTTP协议和工作原理
  3. 微软亚洲研究院多媒体计算组招聘计算机视觉算法实习生
  4. 机器学习并不“万能”
  5. 如何检查项目的需求是否完整
  6. 经典C语言程序100例之四七
  7. java 定时器 的中断程序,STM32定时器中断
  8. leetcode 690. 员工的重要性(dfs)
  9. 【kafka】kafka 消息头的强大功能
  10. 使用Event Bus模式解耦Android App组件间通信
  11. vs2012如何为进行单元测试
  12. mybatisplus 增删改查(普通)
  13. html5双日期时间选择控件,bootstrap daterangepicker双日历时间段选择控件详解
  14. (1) IFC格式简介 (Industry Foundation Class)
  15. sublime text 3211 安装中文包
  16. Obsidian关系图谱如何让节点可以手动拖动
  17. THUSC2019:Illusory World
  18. 《数学之美》阅读笔记
  19. 小单刷题笔记之鲁卡斯队列(浮点数比较)
  20. 游戏小程序有哪些?这3个小程序值得推荐!

热门文章

  1. python二分查找时间复杂度_时间复杂度 二分查找
  2. smbus电池信息读取
  3. Git(二) Git基础入门与实践
  4. 周易六十四卦——震为雷卦
  5. 面试圣经——京东之行
  6. 使用RT-Thread Studio DIY 迷你桌面时钟| 获取温湿度传感器数据(I2C设备驱动+SHT3x软件包)...
  7. 金蝶如何用计算机,怎么把金蝶的报表另存在电脑上?
  8. SpringBoot + geotools 操作 shp文件
  9. css table 左右滑动和强制不换行
  10. 两个鸡蛋和一百层楼的问题