hdu4642
由于题意的规定,对于右下角的方格,如果开始为1,那么Alice每次都会把1变成0,Bob都会把0变成1,因此只可能是Alice赢,同理,当刚开始时为0,那么Alice只会使他变成1,Bob会把它变成0,因此只会是Bob赢。因此题意的关键就在矩阵右下角的数字为1还是为0
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N = 105;
int a[N][N];
int main()
{
int t,n,m;
cin>>t;
while(t--)
{
cin>>n>>m;
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++)
{
scanf("%d",&a[i][j]);
}
}
if(a[n][m])cout<<"Alice"<<endl;
else cout<<"Bob"<<endl;
}
return 0;
}
hdu4639
这个题开始想歪了,想着用Kmp来做,用了两个KMP来找hehe,后来发现了对于重叠的hehe,他是一个斐波拉切数列,可以预处理;同时对于不是重叠的hehe,直接上2^n次方,就这样这个题目一直在wa,其实这个题目没必要这么复杂,本身hehe作为模式串就只有4个字节,而且题意也明确地说明了字符串的大小只有10086,因此可以直接暴力匹配。
一下是两次KMP的代码,wa
#include<iostream>
#include<iomanip>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<climits>
#define mod 10007
#define maxn 11000
using namespace std;
typedef long long lint;
char s[maxn];
char p[maxn];
int next[maxn];
int slen;//模式串长度
int plen;//文本串长度
void get_next1()
{
int i=0;
int j=-1;
next[0]=-1;
while(i<=plen)
{
if(j==-1||p[i]==p[j])
{
++i;
++j;
if(p[i]!=p[j])next[i]=j;
else next[i]=next[j];
}
else j=next[j];
}
}
int kmp1()
{
int i=0;
int j=0;
int count=0;
while(i<slen&&j<plen)
{
if(j==-1||p[j]==s[i])
++i,++j;
else
j=next[j];
if(j>=plen)
{
count++;
j=next[j];
}
}
return count;
}
void get_next2()
{
int i=0,j=-1;
next[0]=-1;
while(i<plen)
{
if(j==-1||p[i]==p[j])
{
i++;
j++;
next[i]=j;
}
else
j=next[j];
}
}
int kmp2()
{
int i=0,j=0;
int num=0;
while(i<slen)
{
if(j==plen)
{
num++;
j=0;
}
if(j==-1||s[i]==p[j])
{
i++;
j++;
}
else
j=next[j];
}
if(j==plen)
num++;
return num;
}
int ans[maxn];
void init()
{
ans[0]=1;
ans[1]=2;
for(int i=2;i<maxn; i++)
{
ans[i]=ans[i-2]+ans[i-1];
ans[i]=ans[i]%mod;
}
}
lint power(lint a,lint b)
{
lint ans=1;
while(b)
{
if(b&1)
{
ans=ans*a%mod;
b--;
}
b=b/2;
a=a*a%mod;
}
return ans;
}
int main()
{
freopen("C:\\Users\\Administrator\\Desktop\\in.txt" , "r" , stdin);
int n;
strcpy(p,"hehe");
int sum1,sum2;
int kk=1;
scanf("%d",&n);
while(n--)
{
scanf("%s",s);
plen=4;
slen=strlen(s);
get_next1();
sum1=kmp1();
get_next2();
sum2=kmp2();
// cout<<"sum1="<<sum1<<" "<<"sum2="<<sum2<<endl;
init();
int k=2*sum2-sum1;
cout<<"Case "<<kk++<<": "<<(ans[sum1-k]*power(2,k)%mod)%mod<<endl;
}
return 0;
}
以下是强哥的AC代码:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define lint __int64
const lint mod=10007;
char s[10100];
short C[5044][2523];
int main()
{
int n,m;
for(int i=1,j;i<5044;++i)
{
C[i][0]=1;
for(j=1;j*2<=i;++j)C[i][j]=(C[i-1][min(j,i-j-1)]+C[i-1][min(j-1,i-j)])%mod;
}
int t,T=1;
while(cin>>t)
{
while(t--)
{
cin>>s;
int size=strlen(s);
lint ans=1,temp;
int z,j;
for(int i=0; i<size;)
{
z=0;
while(i<size)
{
if(s[i]=='h'&&s[i+1]=='e')++z,i+=2;
else
{
++i;
break;
}
}
if(z<2)continue;
temp=1;
for(int k=1; 2*k<=z; ++k)
{
temp=(((temp%mod)+(C[(z-k)][min(k,z-2*k)])))%mod;
}
ans=((ans%mod)*(temp%mod))%mod;
}
cout<<"Case "<<T++<<": "<<ans<<endl;
}
}
return 0;
}
我自己的代码:
/***********1008************************
直接在字符串中查找he的个数,那么hehe的个数就是he的个数-1,就有通过斐波那契数列来累计,通过乘法原理就可以得到答案(类似于分段求解)
*************************************/
#include<iostream>
#include<iomanip>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<climits>
#define mod 10007
#define maxn 10100
using namespace std;
typedef long long lint;
int ans[maxn];
char str[maxn];
void init()
{
ans[0]=1;
ans[1]=2;
for(int i=2; i<maxn; i++)
{
ans[i]=ans[i-1]+ans[i-2];
ans[i]=ans[i]%mod;
}
}
int main()
{
freopen("C:\\Users\\Administrator\\Desktop\\in.txt" , "r" , stdin);
int t;
init();
int len;
int sum;
lint num;
cin>>t;
for(int i=1; i<=t; i++)
{
cin>>str;
len=strlen(str);
num=1;
for(int j=0; j<len;)
{
sum=0;
while(j<len)
{
if(str[j]=='h'&&str[j+1]=='e')++sum,j+=2;
else
{
++j;
break;
}
}
if(sum<2)continue;
num=num*ans[sum-1]%mod;
}
cout<<"Case "<<i<<": "<<num<<endl;
}
return 0;
}