A
题目描述
牛可乐发明了一种n面骰子(点数分别从1到n,掷出每面的概率为1/n)
去给牛牛玩,因为牛牛是个欧皇,所以他想测试一下牛牛的人品,他告诉牛牛,让牛牛投m{}m次骰子,牛牛如果全部投出点数为{}nn的面就算牛牛赢,牛牛很相信自己的人品,就和牛可乐赌一包辣条,说自己肯定可以全部投出点数为{}nn点面,但是牛牛又有点害怕自己打赌输了,想让你提前帮他计算一下他输概率有多少?
思路:暴力算,逆元。
代码:
#include <iostream> #include <bits/stdc++.h> using namespace std; const int mod=1e9+7; inline int read() { int X=0; bool flag=1; char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-') flag=0; ch=getchar();} while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();} if(flag) return X; return ~(X-1); } long long quickpow(long long a, long long b) { if (b < 0) return 0; long long ret = 1; a %= mod; while(b) { if (b & 1) ret = (ret * a) % mod; b >>= 1; a = (a * a) % mod; } return ret; } long long inv(long long a) { return quickpow(a, mod - 2); } int main() { int t; t=read(); while(t--){ long long n,m; n=read(),m=read(); long long q=quickpow(n,m); printf("%lld\n",(q-1)*inv(q)%mod); } return 0; }
B
题目描述
牛牛感觉在上一次赌约中,情况对于自己非常不利,所以决定再赌一场。
这时候,牛蜓队长出现了:第一,绝对不意气用事;第二,绝对不漏判任何一件坏事;第三,绝对裁判的公正漂亮。
牛蜓队长带他们来到了一个棋盘游戏,棋盘左上角是(0,0)(0,0),这个棋盘在(x,y)(x,y)的位置有一个棋子,牛牛和牛可乐轮流移动这个棋子,这个棋子可以左移也可以上移,可以移动一格或者两格,直到不能再移动(即到(0,0)(0,0))的那个人算输。
如果原本在(x,y)(x,y),左移一格即为(x,y -1)(x,y−1),上移一格即为(x-1,y)(x−1,y)
这个时候,牛牛为了弥补上一局的不公平,决定要自己先手,如果两个人都用最优的策略,最后牛牛是否能获胜。
思路:打表发现有规律。打表就看看当前点能否到达一个先手必输点,可以的话该点先手就必胜。
代码:
#include <bits/stdc++.h> using namespace std; int a[3][3]={{0,1,1},{1,0,1},{1,1,0}}; int main(){ int t; scanf("%d",&t); while(t--){ int x,y; scanf("%d%d",&x,&y); if(a[x%3][y%3])printf("yyds\n"); else printf("awsl\n"); } return 0; }
C:模拟,不想写了。
D:
题目描述
a + b的值为x,a&b的值为y,首先需要判断能否有一组a,b满足当前的情况,如果有,那么求出a xor b,否则输出-1
(其中a,b{}>0a,b>0)
思路:基本位运算。
代码:
#include <bits/stdc++.h> using namespace std; typedef long long ll; int main(){ int t; scanf("%d",&t); while(t--){ long long x,y; scanf("%lld%lld",&x,&y); long long a=y,b=y; x-=2*y; for(int i=62;i>=0;i--){ if(y&(1ll<<i))continue; if(x>=(1ll<<i))x-=(1ll<<i),a+=(1ll<<i); } if(x==0)printf("%lld\n",a^b); else printf("-1\n"); } return 0; }
G
题目描述
牛牛每天都要做的事就是读书,从书里找自己喜欢的句子,他每天都会去读一本书,如果牛牛今天读的书的某连续{}kk个字符刚好是牛牛喜欢句子的某个前缀,那么牛牛将得到{}kk点兴奋感,但他每天只能注意到一次自己喜欢的句子(也就是每天只能增加一次兴奋感),也就是说他会尽量去找那个让自己兴奋度增加最多的句子,那么,{}nn天之后牛牛总共最多能有多少兴奋感?
思路:kmp模板,找份模板,稍加修改就行了。
代码
#include <iostream> #include <bits/stdc++.h> using namespace std; int nextt[100005]; void getnext(char *p) { int lenp=strlen(p); nextt[0]=-1; int k=-1; int j=0; while(j<lenp-1) { //p[k]表示前缀,p[j]表示后缀(并没有“真”!) if(k==-1||p[j]==p[k])//j在这 { j++;//j+1在这 k++;//k=k+1 //---->若p[k]=p[j],则next[j+1]=next[j]+1; //下一个位置的next if(p[j]!=p[k])//当p[k]!=p[j]时,与主串不匹配时可以返回到这 { nextt[j]=k; } else//当p[j]=p[k]时与主串匹配时你在j位置不匹配匹配串返回这里当前 //还是 不能与主串匹配,然后还是要返回next[]即next[next[k]] nextt[j]=nextt[k];//优化了 } else { k=nextt[k]; } } return; } int KMP(char *s,char *p) { int i=0,temp=0; int j=0; int lens=strlen(s); int lenp=strlen(p); while(i<lens&&j<lenp) { //如果j=-1(表示第一次开始或者重新开始匹配),即失配于首字符 if(j==-1||s[i]==p[j]) { j++; i++; temp=max(temp,j); } else { //如果j!+-1,或者当前匹配失败 ,则 j=nextt[j]; // i不变,j=next[j] } } return temp; } int main() { int t; char a[100005],b[100005]; scanf("%s",a); getnext(a); scanf("%d",&t); int ans=0; while(t--) { scanf("%s",b); ans+=KMP(b,a); } printf("%d\n",ans); return 0; }
I
题目描述
有一个n×m的网格地图,每个点有个值a ij
,现在牛牛要从(1,1)走到(n,m),他可以往右边或者往下走,每次到一个点会获得当前的点权值,并将权值和mod 1e4+7,当牛牛从不同方式走到(n,m)的时候能获得多少种权值和?
思路:
判断当前点有那些权值,暴力硬算。
代码;
#include <bits/stdc++.h> using namespace std; bool dp[101][101][10007]; int a[101][101]; const int mod=1e4+7; int main(){ int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ scanf("%d",&a[i][j]); a[i][j]%=mod; } } dp[1][1][a[1][1]]=1; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ for(int k=0;k<mod;k++){ dp[i][j][k]|=dp[i-1][j][(k-a[i][j]+mod)%mod]; dp[i][j][k]|=dp[i][j-1][(k-a[i][j]+mod)%mod]; } } } int ans=0; for(int i=0;i<mod;i++)if(dp[n][m][i])ans++; printf("%d\n",ans); return 0; }
J
题目描述
牛牛苦练武功绝学——轻功水上漂,最终没有练成,但是他学会了在树上行走的本领。
这天,牛牛落入了敌人的陷阱,身后有巨石追击,面前有n个点,n-1条边连成一张连通图(一棵树),现在牛牛必须立马选择进入这张图中,但是牛牛发现,这张图有两种不同的点,一旦进入一个点,所有与该点不同类型的点都会消失(相连的边也会消失),牛牛只能走到有边相连的点,牛牛想要自己尽量有更多的点可以活动,那么他可以进入哪些点?
思路:可以按照相同点建边,然后找最大的那几个联通图,或者建边搜相同点,或者并查集找最大的块。
代码:
#include <iostream> #include <bits/stdc++.h> using namespace std; vector<int>edge[200005]; int type[200005],vis[200005]; int dfs(int u,int t) { vis[u]=1; int num=0; for(int i=0;i<edge[u].size();i++){ int v=edge[u][i]; if(vis[v]||type[v]!=t)continue; num+=dfs(v,t); } return num+1; } vector<int>ans,ansn; void dfs1(int u,int t) { vis[u]=1; ans.push_back(u); for(int i=0;i<edge[u].size();i++){ int v=edge[u][i]; if(vis[v]||type[v]!=t)continue; dfs1(v,t); } } int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&type[i]); } for(int i=0;i<n-1;i++){ int u,v; scanf("%d%d",&u,&v); edge[u].push_back(v); edge[v].push_back(u); } int num=0; for(int i=1;i<=n;i++){ if(vis[i])continue; int temp=dfs(i,type[i]); if(temp>num){ ansn.clear(); ansn.push_back(i); num=temp; } else if(temp==num)ansn.push_back(i); } memset(vis,0,sizeof(vis)); for(int i=0;i<ansn.size();i++){ //printf("%d\n",ansn[i]); dfs1(ansn[i],type[ansn[i]]); } sort(ans.begin(),ans.end()); printf("%d\n",ans.size()); for(int i=0;i<ans.size();i++){ printf("%d ",ans[i]); } printf("\n"); return 0; }