要找一个数能够整除数组内其他数,否则输出-1。很明显,要能整除其他数,这个数一定是最小的那一个。若最小的那个数能满足条件,则输出最小的,否则,输出-1。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
#define rep(i, a, n) for(register int i = a; i <= n; ++ i)
#define per(i, a, n) for(register int i = n; i >= a; -- i)
#define ONLINE_JUDGE
using namespace std;
typedef long long ll;
const int mod=1e9+7;
template<typename T>void write(T x)
{
if(x<0)
{
putchar('-');
x=-x;
}
if(x>9)
{
write(x/10);
}
putchar(x%10+'0');
}
template<typename T> void read(T &x)
{
x = 0;char ch = getchar();ll f = 1;
while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
int lcm(int a,int b){return a/gcd(a,b)*b;};
ll ksm(ll a,ll n){//看是否要mod
ll ans=1;
while(n){
if(n&1) ans=((ans%mod)*(a%mod))%mod;
a=((a%mod)*(a%mod))%mod;
n>>=1;
}
return ans%mod;
}
//==============================================================
const int maxn=1e5+10;
int n,a[maxn];
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
//===========================================================
read(n);rep(i,1,n) read(a[i]);
sort(a+1,a+1+n);
int ans=a[1],flag=0;
rep(i,2,n){
if(a[i]%ans){
flag=1;
break;
}
}
if(flag){
puts("-1");
}
else{
write(ans);
}
//===========================================================
return 0;
}
找有没有连续’#'的长度>=k就好了,有则过不去。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
#define rep(i, a, n) for(register int i = a; i <= n; ++ i)
#define per(i, a, n) for(register int i = n; i >= a; -- i)
#define ONLINE_JUDGE
using namespace std;
typedef long long ll;
const int mod=1e9+7;
template<typename T>void write(T x)
{
if(x<0)
{
putchar('-');
x=-x;
}
if(x>9)
{
write(x/10);
}
putchar(x%10+'0');
}
template<typename T> void read(T &x)
{
x = 0;char ch = getchar();ll f = 1;
while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
int lcm(int a,int b){return a/gcd(a,b)*b;};
ll ksm(ll a,ll n){//看是否要mod
ll ans=1;
while(n){
if(n&1) ans=((ans%mod)*(a%mod))%mod;
a=((a%mod)*(a%mod))%mod;
n>>=1;
}
return ans%mod;
}
//==============================================================
const int maxn=3e5+10;
char mp[maxn];
int n,k;
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
//===========================================================
read(n),read(k);scanf("%s",mp+1);
int con=0,pre=0,flag=0;
rep(i,1,n){
if(mp[i]=='#'&&con==0){
con=1;
pre=i;
}
if(mp[i]=='.'&&con==1){
con=0;
if(i-pre>=k){
flag=1;
break;
}
}
}
if(flag||mp[n]=='#') puts("NO");
else puts("YES");
//===========================================================
return 0;
}
这道题感觉好难。。
简单博弈论的一种思路就是求出这个局面能够操作几次,根据操作次数的奇偶性求出结果。
这道题我们把1分为三类:
a、b都能拿的,只有a能拿的,只有b能拿的。然后,我们有三种有效的操作:拿自己的1、拿自己的0堵对方的1,或者两者都有。
最优的策略应该是:首先先拿a、b都能拿的,这样做的收益最大:既能拿到自己的1,也能堵住对方的。
对于a、b都能拿的部分(cnt3),a能拿到cnt3/2+cnt3%2(因为先手),b能拿到cnt3/2
对于只有a、b各自能拿的部分(cnt1,cnt2),a、b都各自拿自己的。若一个人先拿完了,则会开始堵对方。但是,这个只有当a能取的比b的少的时候才可能逆转局势(a先手),所以,只有当cnt1==cnt2-1的时候,a拿走一个才能改变局势。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
#define rep(i, a, n) for(register int i = a; i <= n; ++ i)
#define per(i, a, n) for(register int i = n; i >= a; -- i)
//#define ONLINE_JUDGE
using namespace std;
typedef long long ll;
const int mod=1e9+7;
template<typename T>void write(T x)
{
if(x<0)
{
putchar('-');
x=-x;
}
if(x>9)
{
write(x/10);
}
putchar(x%10+'0');
}
template<typename T> void read(T &x)
{
x = 0;char ch = getchar();ll f = 1;
while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
int lcm(int a,int b){return a/gcd(a,b)*b;};
ll ksm(ll a,ll n){//看是否要mod
ll ans=1;
while(n){
if(n&1) ans=((ans%mod)*(a%mod))%mod;
a=((a%mod)*(a%mod))%mod;
n>>=1;
}
return ans%mod;
}
//==============================================================
int n;
string s,t;
int res1,res2;
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
//===========================================================
cin>>n>>s>>t;
int cnt1=0,cnt2=0,cnt3=0;
rep(i,0,2*n-1){
if(s[i]=='1'&&t[i]=='1') cnt3++;
else if(s[i]=='1') cnt1++;
else if(t[i]=='1') cnt2++;
}
cnt3%=2;
cnt1+=cnt3;
if(cnt1==cnt2-1) cnt2--;
if(cnt1>cnt2) puts("First");
else if(cnt1<cnt2) puts("Second");
else puts("Draw");
//===========================================================
return 0;
}
参考博客:https://www.cnblogs.com/Harry-bh/p/8798883.html
这道题看着有点恐怖,但是,k<=10,因此,若从起点到终点的距离(n+m-1)>k,则一定没有方案,直接输出0就行了,这样,n+m<=10,可以搜索了。
然后要怎么搜索呢?对于颜色,我们可以状压:因为k<=10,1<<10=1024,不大,考虑二进制压缩。我们可以搜索整个图,枚举每个0点的颜色,验证可不可行。因为每个位置只能从上面或左面进入,因此,我们要求点可以选择的颜色,可以从左边和上边的状态得到。设f[i][j]表示到达i、j点的所有路径用过的颜色的二进制压缩,因此,有:f[i]][j]=f[i-1][j] or f[i][j-1]。
对于每个位置x,y:
若x,y本来就有颜色,则,验证当前颜色与f[i][j]中是否有重叠,若有,则该方案不成立,直接return。否则,继续搜索。
若x,y没有颜色,我们就枚举该点的颜色,继续搜索。
所能到达点(x+1,y)说明方案成立,return 1.
但是光这样还过不了,需要剪枝叶:
可行性剪枝:对于一点(x,y),若其到点(n,m)能用的颜色<该点到(n,m)的距离,则不需要搜下去。
对称性剪枝:若该点为0,我们选择了一种颜色i,得到方案数为tmp,则,下次再选一个颜色j,对应方案数也为tmp,所以就不用再搜索了,直接加到res中就行了。
但是注意:这里对颜色i、j有要求,就是i、j等这些颜色必须得是在这个图里没用过的,因为为了避免一种情况,如:
000
010
000
在(1,1)点,我们选颜色1和选颜色2,显然方案数是不一样的。所以,我们需要记录下这个颜色在这个图里是否被用过(记颜色i被用的次数为c[i])。
经过这两个剪枝之后就能顺利通过了。(注意回溯)
留意一个技巧:若j&(i)==0,j|=i之后,则可以通过j^=i还原。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
#define rep(i, a, n) for(register int i = a; i <= n; ++ i)
#define per(i, a, n) for(register int i = n; i >= a; -- i)
#define ONLINE_JUDGE
using namespace std;
typedef long long ll;
const int mod=1e9+7;
template<typename T>void write(T x)
{
if(x<0)
{
putchar('-');
x=-x;
}
if(x>9)
{
write(x/10);
}
putchar(x%10+'0');
}
template<typename T> void read(T &x)
{
x = 0;char ch = getchar();ll f = 1;
while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
int lcm(int a,int b){return a/gcd(a,b)*b;};
ll ksm(ll a,ll n){//看是否要mod
ll ans=1;
while(n){
if(n&1) ans=((ans%mod)*(a%mod))%mod;
a=((a%mod)*(a%mod))%mod;
n>>=1;
}
return ans%mod;
}
//==============================================================
const int maxn=1000+100;
int n,m,k;
int mp[maxn][maxn];
int f[maxn][maxn];
int c[maxn];
//ll re[maxn];
inline int cal(int x){
//if(re[x]!=-1) return re[x];
//ll&res=re[x];
ll cnt=0;
rep(i,1,k){
if(!(x&(1<<i))) cnt++;
}
return cnt;
}
ll solve(int x,int y){
if(x>n) return 1;
int nxtx=x,nxty=y+1;
if(nxty>m) nxty%=m,nxtx+=1;
int flag=0;
ll tmp=0;
f[x][y]=(f[x-1][y]|f[x][y-1]);
int num=cal(f[x][y]);
if(num<n-x+m-y+1) return 0;
ll res=0;
if(mp[x][y]){
if(!(f[x][y]&(1<<mp[x][y]))){
f[x][y]|=(1<<mp[x][y]);
res=(res+solve(nxtx,nxty))%mod;
f[x][y]^=(1<<mp[x][y]);
}
}
else{
rep(i,1,k){
if(!(f[x][y]&(1<<i))){
if(c[i]==0){
if(flag){res+=tmp;res%=mod;}
else{
flag=1;
c[i]++;
f[x][y]|=(1<<i);
tmp=solve(nxtx,nxty);
f[x][y]^=(1<<i);
c[i]--;
res+=tmp;
res%=mod;
}
}
else{
c[i]++;
f[x][y]|=(1<<i);
res+=solve(nxtx,nxty);
f[x][y]^=(1<<i);
c[i]--;
res%=mod;
}
}
}
}
return res;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
clock_t c1 = clock();
//===========================================================
read(n),read(m),read(k);
//memset(re,-1,sizeof(re));
rep(i,1,n) rep(j,1,m) read(mp[i][j]),mp[i][j]?c[mp[i][j]]++:23333;
if(n+m-1>k){
puts("0");
return 0;
}
ll ans=solve(1,1);
write(ans);
//===========================================================
std::cerr << "Time:" << clock() - c1 << "ms" << std::endl;
return 0;
}