题目链接
知识一览
01 - 开灯问题(数组反转/结论题)
02 - 杨辉三角求某行某列问题/组合数问题
03 - 二分+DFS(D题)
题目列表
快输
static class FastReader{
BufferedReader br;
StringTokenizer st;
String tmp;
public FastReader() {
br=new BufferedReader(new InputStreamReader(System.in));
}
String next() {
while(st==null||!st.hasMoreElements()) {
try {
st=new StringTokenizer(br.readLine());
}catch(IOException e) {
e.printStackTrace();
}
}
return st.nextToken();
}
int nextInt() {
return Integer.parseInt(next());
}
long nextLong(){return Long.parseLong(next());}
String nextLine() {
String str="";
try {
str=br.readLine();
}catch(IOException e) {
e.printStackTrace();
}
return str;
}
boolean hasNext(){
if(st!=null&&st.hasMoreTokens())return true;
try {
tmp=br.readLine();
st=new StringTokenizer(tmp);
}catch(IOException e) {
return false;
}
return true;
}
}
static PrintWriter out=new PrintWriter(
new BufferedWriter(new OutputStreamWriter(System.out)));
static FastReader sc=new FastReader();
D 逃离符联网(二分+DFS)
输入描述:
第一行两个正整数n,m,代表《符链网》有n行m列。(1≤n,m≤610)
接下来n行每行m个正整数,第i行第j个数字代表坐标为(i,j)房间虚空兽的战斗力。(0≤战斗力≤n∗m)
接下来一行给出两个正整数x,y,代表会被扔到坐标为(x,y)的房间。(1≤x≤n,1≤y≤m)
接下来一行给出两个正整数w,z,代表符链网的出口在坐标为(w,z)的房间。(1≤w≤n,1≤z≤m)
输出描述:
输出一个正整数,表示你最快能在多少天之内溜出去。
示例1
输入
3 3
1 0 2
8 8 3
6 8 4
1 1
3 1
输出
8
说明
由于初始房间有战斗力为1的虚空兽,使用道具转送到一天之后才能进,进去之后发现右边虚空兽战斗力为0,所以你直接进,然后在等待1天后就又能继续进入右边的房间(因为你跳转了一天+在(1,2)房间等待了一天,虚空兽战斗力会下降2变为0消失),再过1天目前你下方战斗力为3的虚空兽也会消失于是进入,再过一天,目前你下方战斗力为4的虚空兽也消失,最终再过4天之后,此时距离你进入已经过去8天,所以目前你左边战斗力为8的虚空兽也消失了,出口战斗力为6的虚空兽在第六天时就已经消失所以你可以直接出去。所以最终用时为8天。PS:解释所给出的走法只是若干种走法中的一种,随便怎么走都行,只要保证时间最短。
static int n,m,x,y,w,z;
static int mp[][]=new int[620][620];
static boolean vis[][]=new boolean[620][620];
static int dir[][]={{1,0},{-1,0},{0,1},{0,-1}};
public static void main(String[] args) {
n=sc.nextInt();
m=sc.nextInt();
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
mp[i][j]=sc.nextInt();
}
}
x=sc.nextInt();y=sc.nextInt();
w=sc.nextInt();z=sc.nextInt();
int l=mp[x][y],r=(int)1e9;
while(l<r) {
int mid=(l+r)>>1;
for(int i=0;i<620;i++)
Arrays.fill(vis[i],false);
if(check(x,y,mid)) r=mid;
else l=mid+1;
}
out.println(l);
out.flush();
}
static boolean check(int x,int y,int cur){//判断能否在cur天之内溜出去
if(x==w&&y==z)return true;
vis[x][y]=true;
boolean f=false;
for(int i=0;i<4;i++){
int dx=x+dir[i][0],dy=y+dir[i][1];
if(dx<1||dx>n||dy<1||dy>m)continue;
if(!vis[dx][dy]&&mp[dx][dy]<=cur)f|=check(dx,dy,cur);
}
return f;
}
G 带黄狗的礼物(杨辉三角问题)
题目描述
带黄狗要去超市买礼物,有n种礼物。它需要买m个,每种礼物可以重复选择,请问带黄狗可以有多少种买礼物的方案。
输入描述:
第一行输入两个整数n(1≤n≤10^7 ), m(1≤m≤10^7)
输出描述:
输出一个整数代表一个答案。需要对10^9+7取模
示例1
输入
2 2
输出
3
说明
一共有(1, 1), (1, 2), (2, 2)三种方案,(2, 1)和(1, 2)相同算作一种
备注:
两个方案不同指,两种方案至少存在一种物品的数量不同。
思路:杨辉三角图和结果图对比如下
杨辉三角图
结果图可知,对于该题,有n种礼物,需要买m个的结果对应第n+m行,m+1列的杨辉三角数。
重点即是要求某行某列的杨辉三角数是多少。
求某行某列的杨辉三角数是多少
求法详解
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using namespace std;
typedef long long ll;
const int mod=1e9+7;
int n,m;
ll ksm(ll a,ll b,ll p){//求逆元
ll res=1;
while(b){
if(b&1) res=res*a%p;
a=a*a%p;
b/=2;
}
return res;
}
ll f(int n,int m,ll s1,ll s2)
{
int i;
int t=n-m;
for(i=n-1;i>t;i--)
s1=s1*i%mod;
for(i=1;i<m;i++)
s2=s2*i%mod;
return s1*ksm(s2,mod-2,mod)%mod;
}
int main() {
IOS
cin>>n>>m;
ll s1=1,s2=1;
cout<<f(n+m,m+1,s1,s2)<<endl;
}
类似的问题:D 真正的卡尔
题目连接
该题需要求一系列的值,可以打表求组合数
static int mod=998244353,N=1010;
static long c[][]=new long[N][N];
public static void main(String[] args) {
int t=sc.nextInt();
init();
while(t-->0) {
int a=sc.nextInt();
int b=sc.nextInt();
out.println(c[a][b]);
out.flush();
}
}
private static void init() {
// TODO Auto-generated method stub
for(int i=1;i<N;i++){
c[i][1]=i;c[1][i]=1;
}
for(int i=2;i<N;i++) {
for(int j=2;j<N;j++) {
c[i][j]=(c[i][j-1]+c[i-1][j])%mod;
}
}
}
杨辉三角打表求法
#include <stdio.h>
//杨辉三角
int main()
{
int n;
printf("请输入要打印的行数:");
scanf("%d",&n);
int a[100][100];
for(int i=0;i<n;i++)
{
a[i][0]=1;
a[i][i]=1; //先将杨辉三角每行的第一个和最后一个赋值为1
}
for(int i=2;i<n;i++) //已知每个数等于它上方两数的之和
{
for(int j=1;j<i;j++)
{
a[i][j]=a[i-1][j-1]+a[i-1][j];
}
}
for(int i=0;i<n;i++) //打印输出
{
for(int j=0;j<=i;j++)
{
printf("%d ",a[i][j]);
}
printf("\n");
}
}
I 自习室的灯
类似问题:HENAUOJ - 1148
题意:
把教室从1到n编号,从1开始,反转一下能整除数字1的房间号的对应房间灯的开关,然后再反转能整除数字2的房间的开关,再反转能整除数字3的房间的开关…再反转能整除数字n的房间的开关。请问经过n次反转之后,有几间房的灯是开着的,并输出开灯的房间号。房间的灯开始全是熄灭的,反转开关就是指如果灯亮着就熄灭,熄灭就点亮。
思路:亮着灯的个数为n^(1/2)(即根号n),编号为n以内的完全平方数。
public static void main(String[] args) {
long n=sc.nextLong();
long ans=(long)Math.sqrt(n),a;
out.print(ans+" ");
for(long i=1;i<=ans;i++){
a=i*i;
out.print(a+" ");
}
out.flush();
}