今天三个题的考试。
题解(不会的T3)原作:
https://blog.csdn.net/Ab_Ever/article/details/77185812
先说会的T1:
T1实际上是一个水题
主要思路是要进行查找
于是就有了暴力的搜索方式:枚举
没有优化,不知道可否过。
上题目:
小J的五子棋
小J非常热爱玩游戏,尤其喜欢五子棋。
五子棋是一款这样的游戏:
在一个N*N的网格上,玩家依次在格子上放下棋子,如果棋子在同一横排、同一竖排、同一斜线(有两条不同的斜线,从左上到右下以及从右上到左下)连续出现了五个,那么就满足了胜利条件。需要注意的是,与一般的五子棋不同,我们只考虑一个玩家的棋子,即不存在不同的颜色。
小J于是开始了一盘紧张刺激的五子棋。
小J的玩法和一般的玩法不同,小J喜欢先写下一个长度为M的放置棋子序列,然后依次放置棋子,直到满足胜利条件为止,或者说序列上的棋子都放置完了。
那么,小J想知道会在放置第几个棋子之后达到胜利条件。
输入格式:
第一行两个正整数N,M,意义见题面。
接下来M行,每行两个整数x,y.(x,y)表示放置的棋子的坐标。保证1<=x,y<=N.
输出格式:
一行一个整数,表示达到胜利条件时放置的棋子。如果达不到胜利条件,输出-1.
输入样例:
5 5 1 1 2 2 3 3 4 4 5 5
输出样例:
5
数据规模:
对于30%的数据,1<=N,M<=10.
对于60%的数据,1<=N,M<=100.
对于100%的数据,1<=N<=20000,M<=200000.
数据范围真小哈哈哈哈
我们边输入边判断:
这样先输出的一定是最先放置的最优解。
判断什么呢?先横着枚举x轴,直到遇到没有棋子的棋盘格子,记下连号cnt值(左右各一遍),
然后再y轴,两条对角线,各种枚举,最后发现都没有连起来>=5的,就返回false就是了。
上代码:
#include <iostream> #include <cstdio> #include <fstream> #include <bitset> using namespace std; bitset<400040001>mp;//存棋盘 int n,m; bool judge(int x,int y) { int cnt=0;//棋子计数器 //跑y轴 for (register int i=y;i>0;i--) { if (mp[(x-1)*n+i]==1)cnt++; else break; } for (register int i=y+1;i<=n;i++) { if (mp[(x-1)*n+i]==1)cnt++; else break; } if (cnt>=5)return true; //跑x轴 cnt=0; for (register int i=x;i>0;i--) { if (mp[(i-1)*n+y]==1)cnt++; else break; } for (register int i=x+1;i<=n;i++) { if (mp[(i-1)*n+y]==1)cnt++; else break; } if (cnt>=5)return true; //跑斜线 cnt=0; for (register int i=x,j=y;i>0&&j>0;i--,j--) { if (mp[(i-1)*n+j]==1)cnt++; else break; } for (register int i=x+1,j=x+1;i<=n&&j<=n;i++,j++) { if (mp[(i-1)*n+j]==1)cnt++; else break; } if (cnt>=5)return true; //另外一条 cnt=0; for (register int i=x,j=y;i>0&&j<=n;i--,j++) { if (mp[(i-1)*n+j]==1)cnt++; else break; } for (register int i=x+1,j=y-1;i<=n&&j>0;i++,j--) { if (mp[(i-1)*n+j]==1)cnt++; else break; } if (cnt>=5)return true; return false; } int main() { ifstream fin("A.in"); ofstream fout("A.out"); fin>>n>>m; //cin>>n>>m; int x,y; for (register int i=1;i<=m;i++) { fin>>x>>y; //cin>>x>>y; mp[(x-1)*n+y]=1; if (judge(x,y)) { fout<<i;//若ok,就输出然后就停了 //cout<<i; return 0; } } fout<<"-1";//都不ok就输出-1 //cout<<"-1"; return 0; }
另外,因为内存限制原因,我们不要开map,也不要开bool,bitset水过去就好了。
(STL真香)
T2
小J爱gcd
最大公约数,greatest common divisor,简称gcd。
对于非负整数x与y的最大公约数,为最大的正整数z,使得x与y均是z的整数倍。特定地,gcd(0,0)=0,gcd(0,x)=x.
小J非常清楚一点:gcd是数学王国的统治者,一切函数都要臣服于gcd之下,哪怕是增长速度极快的指数函数也不例外。
小J非常想知道当统治者gcd与速度之王结合在一起会是怎么样的效果,于是小J想出了这么一个题目:求解gcd(a^b,c^d).
小J于是将问题交给了你。为了运算方便,将最后的结果对1e9+7取模后输出。
输入格式:
一行四个非负整数a,b,c,d。意义见体面。
输出格式:
一行一个整数,为所求的答案。
输入样例:
2 3 4 1
输出样例:
4
样例解释:
数据规模:
对于30%的数据,a,b,c,d<=10.
对于60%的数据,a,b,c,d<=10000.
对于100%的数据,a,b,c,d<=10^9.
行吧,这个题我用的是快速幂+GCD然后%%%
快速幂不多说,关键是gcd的时候要返回什么值,
外加一堆特判,水过去算了。(应该不是满分解)
上代码:
#include <iostream> #include <fstream> #include <cstdio> using namespace std; typedef long long int lli; inline lli quick_pow(lli a, lli b, lli c) { if (a==0)return 0; if (a==1)return 1; if (b==0)return 0; lli res = 1; a %= c; while (b) { if (b & 1) res = (res * a) % c; a = (a * a) % c; b >>= 1; } return res; } inline lli gcd(lli a,lli b) { if (a==0&&b==0)return 0; else if (a!=0&&b==0)return b; else if (a==0&&b!=0)return a; else { while (a%b!=0) { lli temp=a; a=b; b=temp%b; } return b; } } lli min(lli a,lli b) { return a<=b?a:b; } int main() { ofstream fout("B.out"); ifstream fin("B.in"); lli a,b,c,d,degcd,ans; /*fin*/fin>>a>>b>>c>>d; //degcd=gcd(a,c); //ans=quick_pow(degcd,min(b,d),1e9+7); ans=gcd(quick_pow(a,b,1e9+7),quick_pow(c,d,1e9+7)); /*fout*/fout<<ans; return 0; }
T3不会,看上面的博客吧。
End.