A The GCD of Fibonacci Numbers
题意: 求gcd(fn,fm)
题解: 主要是题意提示的比较明显,题意gcd(fn,fm)<=45,所以先求出前45项的斐波那契数列然后输出f[gcd(n,m)]
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std ;
const int N = 50 ;
int f[N] ;
int main(){
f[0] = 0 , f[1] = 1 ;
for (int i=2 ; i <= 45; ++i)
f[i]=f[i-1]+f[i-2] ;
int t ; scanf("%d",&t);
while(t--){
int n , m ;
scanf("%d%d",&n,&m) ;
printf ("%d\n",f[__gcd(m,n)]) ;
}
return 0 ;
}
B Xu1024’s treasure chest
题意: 给出A求 符合B^2 - A^2 = C^2 - B^2.的B和C
题解: 看了别人的题解就是说带入A=1可以得出B=5,C=7所以B=5A,C=7A,。。。。。。。。。。(os:还有这种解法。。。。。)
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std ;
typedef long long ll;
const int mod = 1e9 ;
int main(){
ll a ; scanf("%lld",&a) ;
if(a==0) printf("-1\n") ;
else printf("%lld %lld\n",5*abs(a),7*abs(a)) ;
return 0 ;
}
C Binbin’s treasure map
题意: 迷宫中#是不能走的,.是能走的,$是可以获得一个金币的,走的时候可以任意选择一个点开始,中间有一个机会可以换到任意一个点,问最多能获得多少金币。
题解: 搜索两个联通块就行然后选择两个最多金币的联通块输出,但是有个要注意的点就是,边界外的一圈是可以走的,所以输入的时候边界是1~n然后判断出界的时候是要0 ~n+1才能过
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std ;
const int N = 505 ;
bool vis[N][N] ;
char g[N][N] ;
int n , m , cnt ;
int ans[N*N] ;
int dir[4][2] = {{-1,0},{0,-1},{1,0},{0,1}} ;
bool cmp(int a , int b){
return a > b ;
}
void dfs(int dx , int dy){
if(g[dx][dy] == '$') ++ cnt ;
vis[dx][dy] = true ;
for(int i = 0 ; i < 4 ; ++ i){
int x = dx + dir[i][0] ;
int y = dy + dir[i][1] ;
//边界从0~n+1
if(x>=0&&x<=n+1&&y>=0&&y<=m+1&&!vis[x][y]&&g[x][y]!='#')
dfs(x,y) ;
}
return ;
}
int main(){
cin >> n >> m ;
for(int i = 1 ; i <= n ; ++ i)
for(int j = 1 ; j <= m ; ++ j)
cin >> g[i][j] ;
int k = 0 ;
for (int i = 1 ; i <= n ; ++ i){
for(int j = 1 ; j <= m ; ++ j){
if(vis[i][j] && g[i][j] == '$'){
cnt = 0 , dfs(i,j) ;
ans[k++] = cnt ;
}
}
}
sort(ans,ans+k,cmp) ;
cout << ans[0]+ans[1] << endl ;
return 0 ;
}
D Day Passing
题意: 给出周几和n,m问nm天后是周几
题解: 其实就是一个快速幂取模,但是n的范围为1e100000要先处理一下,在输入的时候(字符串转为数时一遍转一遍取模%7)
#include <cstdio>
#include <iostream>
#include <map>
using namespace std ;
typedef long long ll ;
string s[7] = {"Mon","Tue","Wed","Thu","Fri","Sat","Sun"} ;
ll fast(ll a , ll b , ll p){
a %= p ;
ll res = 1 ;
while(b){
if(b&1) res = res*a%p ;
a = a*a%p ;
b >>= 1 ;
}
return res ;
}
int main(){
string day , x ; ll n , m ;
cin >> day >> x >> m ;
for (int i = 0 ; i <x.length() ; ++ i)
n = (n*10+(x[i]-'0'))%7 ;//输入处理
int i = 0 ;
for( ;i<7;++i)
if(s[i]==day) break ;
ll pos = fast(n,m,7) ;//快速幂取模
cout << s[(i+pos)%7] << endl ;
return 0 ;
}
F Kuangyeye’s Game
题意:给出若干点的坐标问是否全部在同一条直线上
题解:每两点之间斜率相同即可。
#include <cstdio>
#include <cmath>
const int eps=1e-6 ;
const int N = 1005 ;
int a[N][2] , n ;
int main(){
scanf("%d",&n) ;
for(int i = 0 ; i < n ; ++ i)
scanf("%d%d",&a[i][0],&a[i][1]) ;
if(n <= 2) {
printf ("Yes\n") ;
return 0 ;
}
int x = a[1][0]-a[0][0] , y = a[1][1]-a[0][1] ;
bool flag = true ;
for(int i = 2 ; i < n ; ++ i){
if(y*(a[i][0]-a[0][0]) != x*(a[i][1]-a[0][1])){
flag = false ;
break ;
}
}
if(flag) printf ("Yes\n") ;
else printf("No\n") ;
return 0 ;
}
G Buy Keys
题意: 10块钱可以买三把钥匙,3块钱可以买1把钥匙,给出金额问能买最少的钥匙数并且不剩下钱。
题意: 从n/10到0从大到小一个个试能否与3组合如果可以就计算输出,不行就输出orz
#include <cstdio>
int cal(int n){
int a=n/10 ;
for(int i=a;i>=0;--i){//从大到小保证最后的钥匙数最少
if((n-i*10)%3==0)//匹配成功返回i值
return i ;
}
return -1 ;//10和3不能组合
}
int main(){
int n ;
scanf("%d",&n) ;
if(cal(n)==-1) printf("orz\n");
else printf("%d\n",3*cal(n)+(n-10*cal(n))/3) ;
return 0 ;
}
H Dice
题意: 玩游戏最多玩n轮,只要有一轮赢了就不再继续玩,问赢的概率
题解: 直接模拟,前一轮的当前计算赢的概率乘于当前轮赢的概率(0.5)
#include <cstdio>
int main(){
int t ; scanf("%d",&t);
while(t--){
int n ; scanf("%d",&n) ;
double ans = 0 , temp = 0 ;
for(int i=1;i<=n;++i){
ans += 0.5*(1-temp) ; temp = ans ;
}
printf ("%.4lf\n",ans) ;
}
}
J Fake Nim
题意:A和B两人轮流取石子,有n堆石头,A只取一堆石头的偶数个,B只取奇数个,当少于两个石头时A不会取,谁拿走最后一块石头谁就赢。
题解:还是看看大佬的题解吧。。。。。(至今不会博弈。。。。。)
#include <cstdio>
typedef long long ll ;
int main(){
int n ; ll x ;
scanf("%d",&n) ;
int odd = 0 ;
for(int i = 0 ; i < n ; ++ i)
scanf("%d",&x) , odd += x&1 ;
if(n==1 && odd==0) printf("DaDa\n") ;
else printf("TuTu\n") ;
return 0 ;
}
L Special number
题意: 一个数能被少于三个数整除的数为特别数,给出一个区间[L,R]问里面的特别数有几个。
题解: 其实就是在问素数有几个,但是要注意的是范围包括0,而0不是素数。
#include <cstdio>
bool isprime(int n){
if(n==0) return false ;
if(n <= 3) return true ;
for (int i=2 ; i*i <= n+1 ; ++ i)
if(n%i == 0) return false ;
return true ;
}
int main(){
int l , r , cnt = 0 ;
scanf("%d%d",&l,&r) ;
for(int i=l ; i<=r ; ++i){
if(isprime(i)) ++cnt ;
}
printf("%d\n",cnt);
return 0 ;
}
M XOR Sum
题意:给出区间[L,R]问该区间异或和为多少。
题解:l和r的数据范围到1e18肯定不能直接遍历,遍历100打表发现没四个数异或为0,所以中间每四个就不用去算了,算头尾不是四的倍数的就行。
#include <cstdio>
#include <iostream>
using namespace std ;
typedef long long ll ;
int main(){
ll l,r , ans = 0 ;
cin >> l >> r ;
if(r-l > 4){
ll flag = l ;
for(ll i = l ; i <= r ; ++ i){
if(i%4 != 0) ans ^= i ;
else break ;
}
for(ll i = r ; i >= l ; -- i){
if((i+1)%4!=0) ans ^= i ;
else break ;
}
}
else
for(ll i = l ; i <= r ; ++i) ans ^= i ;
cout << ans << endl ;
return 0 ;
}