题目链接
A.脑筋急转弯
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
int n,a[N];
int main() {
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
if(a[i]==1)return cout<<-1,0;
}
cout<<1<<'\n';
return 0;
}
B.所有情况判一判
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
int a[5],b[5];
int main() {
ios::sync_with_stdio(false);
for(int i=1;i<=3;i++){
cin>>a[i]>>b[i];
}
if(a[2]+a[3]<=a[1]&&max(b[2],b[3])<=b[1])cout<<"YES\n";
else if(b[2]+b[3]<=b[1]&&max(a[2],a[3])<=a[1])cout<<"YES\n";
else{
swap(a[2],b[2]);
if(a[2]+a[3]<=a[1]&&max(b[2],b[3])<=b[1])cout<<"YES\n";
else if(b[2]+b[3]<=b[1]&&max(a[2],a[3])<=a[1])cout<<"YES\n";
else{
swap(a[3],b[3]);
if(a[2]+a[3]<=a[1]&&max(b[2],b[3])<=b[1])cout<<"YES\n";
else if(b[2]+b[3]<=b[1]&&max(a[2],a[3])<=a[1])cout<<"YES\n";
else{
swap(a[2],b[2]);
if(a[2]+a[3]<=a[1]&&max(b[2],b[3])<=b[1])cout<<"YES\n";
else if(b[2]+b[3]<=b[1]&&max(a[2],a[3])<=a[1])cout<<"YES\n";
else cout<<"NO\n";
}
}
}
return 0;
}
C.补成一个梯形,去掉多余的部分
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
int a[N],b[N];
LL get(){
LL ans=0;
// for(int i=1;i<=6;i++)cout<<a[i]<<' ';
int num=a[2]+1;
for(int i=1;i<=a[6]+a[1];i++){
ans+=2*num-1;
num++;
}
for(int i=1;i<=a[6];i++){
ans-=(2*i-1);
}
for(int i=1;i<=a[4];i++){
ans-=(2*i-1);
}
return ans;
}
int main() {
//120
ios::sync_with_stdio(false);
for(int i=1;i<=6;i++)cin>>a[i];
//
cout<<get()<<'\n';
return 0;
}
D.直接分治判断一下即可
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
char a[N],b[N];
int ch(int l,int r,int x,int y){
int dx=l+r>>1;
int dy=x+y>>1;
int sta=0;
for(int i=l;i<=r;i++){
if(a[i]!=b[x+i-l]){
sta=1;
break;
}
}
// cout<<l<<' '<<r<<' '<<x<<' '<<y<<' '<<sta<<endl;
if(!sta)return 1;
if((r-l+1)%2==0 && (y-x+1)%2==0){
if(ch(l,dx,x,dy)&&ch(dx+1,r,dy+1,y))return 1;
if(ch(l,dx,dy+1,y)&&ch(dx+1,r,x,dy))return 1;
}
return 0;
}
int main() {
ios::sync_with_stdio(false);
cin>>a+1>>b+1;
int l=strlen(a+1);
if(ch(1,l,1,l))cout<<"YES\n";
else cout<<"NO\n";
return 0;
}
E.
题意:一个n*m的棋盘,从左上角走到右下角,有m个违法格子不能经过,问你有多少种方式。
答案显然等于:总方案-不合法方案。
如何计算不合法方案呢?
我们对每个不能经过的格子进行讨论:一个格子所能贡献的方案为,左上角到它的方案乘以它到右下角的方案,这样显然会多算很多。 那么用分治的思想来看的话,每个不能经过的格子就是一个小棋盘,找到从左上角到它的位置且不经过违法点的方案数 fi。显然就可以解决这个问题了。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
LL fac[N],inv[N];
const LL mod=1e9+7;
LL km(LL a,LL b){
LL ans=1;
while(b){
if(b&1)ans=a*ans%mod;
b>>=1;
a=a*a%mod;
}
return ans;
}
int a[N],b[N],n,m,k;
void init(){
fac[0]=1;
for(int i=1;i<N;i++)fac[i]=fac[i-1]*i%mod;
inv[N-1]=km(fac[N-1],mod-2);
for(int i=N-2;i>=0;i--)inv[i]=inv[i+1]*(i+1)%mod;
}
LL get(int x,int y){
return fac[x]*inv[y]%mod*inv[x-y]%mod;
}
struct uzi{
int a,b;
bool operator <(const uzi &t)const{
if(a==t.a)return b<t.b;
return a<t.a;
}
}p[N];
LL tmp[N];
int main() {
ios::sync_with_stdio(false);
init();
cin>>n>>m>>k;
for(int i=1;i<=k;i++)cin>>p[i].a>>p[i].b;
LL ans=get(n+m-2,m-1);
sort(p+1,p+1+k);
for(int i=1;i<=k;i++){
int sta=0;
LL tot=0;
tmp[i]=get(p[i].a+p[i].b-2,p[i].b-1);
for(int j=1;j<i;j++){
if(p[j].b<=p[i].b){
sta=1;
tot+=tmp[j]*get(p[i].a+p[i].b-p[j].a-p[j].b,p[i].b-p[j].b)%mod;
tot%=mod;
}
}
if(!sta){
tmp[i]=get(p[i].a+p[i].b-2,p[i].b-1);
}else{
tmp[i]-=tot;
tmp[i]=(tmp[i]+mod)%mod;
}
ans-=tmp[i]*get(n+m-p[i].a-p[i].b,m-p[i].b)%mod;
ans=(ans+mod)%mod;
}
cout<<ans<<'\n';
return 0;
}