没想到居然是中文题。。。非常菜,在两道签到题上卡了一个多小时。比赛的时候B题(在哈尔滨的寒风中)居然没做出来,只出了三题,赛后才知道如此简单。。。还是水平不足。以后要更加努力啊。。。下面写一下最简单的四道题的题解:
A. 唐纳德先生和假骰子
题意不多说了吧。。。直接暴力即可,不要忘了取模。第一遍没读懂题,菜哭。
AC代码:
#include<iostream>
#include<iomanip>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<string>
#include<queue>
#include<vector>
#include<map>
using namespace std;
const int mx=500010;
int a[mx],b[mx],c[mx];
char s[mx];
char ss[mx];
int x,y,d,sum;
int e,p,n,ans;
bool f;
int main()
{
int i,j,k;
int cas=1;
while(scanf("%d",&n)!=EOF)
{
memset(c,0,sizeof(c));
for(i=0;i<6;i++)
{
scanf("%d",&a[i]);
}
for(i=0;i<6;i++)
{
scanf("%d",&b[i]);
}
for(i=0;i<6;i++)
for(j=0;j<6;j++) c[(a[i]+b[j])%n]++;
for(j=1;j<n;j++)
{
if(c[j]!=c[0]) break;
}
if(j==n) printf("YES\n");
else printf("NO\n");
}
return 0;
}
B. 在哈尔滨的寒风中
官方题解说的还是比较详细的。比赛的时候考虑到了组合数,没想到特殊情况特判,其他情况直接组合数就可以一下出来。
对于所有 ≥3×4 的棋盘,我们可以断言所有砖之间可以互相到达,此时答案为 Cnm 2,即nm*(nm-1)/2。
当棋盘大小为 3×3 时,通过简单的模拟可以发现外围的 8 块砖可以互相到达,此时答案为 C8 2。也就是8*7/2=28,特判即可。
当棋盘大小为 2×n 时,我们发现不同奇偶不同的行/列交替可达,此时有 2 组(n/2)的联通块与两组 n−(n/2)的联通块,答案为 2×(C(n/2) 2) +2×C(n−(n/2) 2),就是(n/2)*(n/2-1)+(n-(n/2)*((n-n/2)-1))。
当棋盘大小为 1×n 时,没有合法的马步,此时答案为 0。注意结果要用long long。
AC代码:
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<string>
#include<queue>
#include<vector>
#include<map>
#include<set>
using namespace std;
const int mx=100100;
const int ssize=26;
long long ans,n,m,k,c[mx];
char s[mx],ss[mx];
struct node{
int sum;
int id;
bool operator<(const node a)const{
return (sum>a.sum)||(sum==a.sum&&id<a.id);
}
}d[27];
int main()
{
int T;
int nn,mm;
while(scanf("%lld%lld",&n,&m)!=EOF)
{
if(n==1||m==1) printf("0\n");
else if(n==3&&m==3) printf("28\n");
else if(n==2)
{
k=m-m/2;
m/=2;
printf("%lld\n",m*(m-1)+k*(k-1));
}
else if(m==2)
{ k=n-n/2;
n/=2;
printf("%lld\n",n*(n-1)+k*(k-1));
}
else printf("%lld\n",m*n*(m*n-1)/2);
}
return 0;
}
C. 易位构词
可以说,题解和我的思路一样。。。就是出现次数最多的字母多于总长度的一半就impossible,否则从出现最多的字母开始用出现第二多的字母替换,第二多的字母不够用了就用第三多的字母,直到出现次数最少的字母被用完,再用出现次数最多的字母去替换,自己可以画画试试,这样一定有结果而且一定是正确的。
AC代码:
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<string>
#include<queue>
#include<vector>
#include<map>
#include<set>
using namespace std;
const int mx=100100;
const int ssize=26;
int ans,n,k,c[mx];
char s[mx],ss[mx];
struct node{
int sum;
int id;
bool operator<(const node a)const{
return (sum>a.sum)||(sum==a.sum&&id<a.id);
}
}d[27];
int main()
{
int T;
int m;
int nn,mm;
while(scanf("%s",s)!=EOF)
{
int i,j;
memset(c,0,sizeof(c));
n=strlen(s);
int summ=0;
for(int i=0;i<n;i++)
{
if(c[s[i]-'a']==0) summ++;
c[s[i]-'a']++;
}
int ma=-1;
ans=0;
for(i=0;i<26;i++)
{
if(c[i]>ma) ma=c[i];
ans+=c[i];
d[i].sum=c[i];
d[i].id=i;
}
sort(d,d+26);
k=1;
if(2*ma-ans>0) printf("impossible\n");
else {
for(i=0;i<summ;i++)
{
for(j=0;j<n;j++)
{
if(s[j]==d[i].id+'a') {
if(d[k].sum==0) k++;
if(k==summ) k=0;
//cout<<s[j]<<k<<d[k].id<<endl;
d[k].sum--;
ss[j]=d[k].id+'a';
}
}
}
for(i=0;i<n;i++) printf("%c",ss[i]);
puts("");
}
}
return 0;
}
G1. 唐纳德与子串 (Easy)
刚开始用KMP做一直WA,不知为何,卡了半个多小时后用暴力一下就过了。。。Orz
直接找。。。
AC代码:
#include<iostream>
#include<cmath>
#include<string>
#include<string.h>
#include<algorithm>
#include<queue>
#include<vector>
#include<cstdio>
#include<map>
using namespace std;
const int mx=110001;
int m,n,ans,x,y;
map<int, string> mm;
int f[mx];
int a[mx];
void find(int x,int y){
int j=0;string t1=mm[x],t2=mm[y];
for(int i=0;i<a[x];i++)
{
if(j&&t1[i]!=t2[j]) j=f[j];
if(t1[i]==t2[j]) j++;
if(j==a[y]) ans++;
}
}
void getFail(int x,int y)
{
f[0]=f[1]=0;
string t1=mm[x],t2=mm[y];
for(int i=1;i<a[y];i++)
{
int j=f[i];
while(j&&t2[i]!=t2[j]) j=f[j];
f[i+1]=t2[i]==t2[j]?j+1:0;
}
}
int main()
{
ios::sync_with_stdio(false);
int T;
int i,j,k,t,n;
int ma;
string s3;
string s2;
while(cin>>s2)
{
int len=s2.length();
s2[len]='Q';
//mm[2]=s1;
cin>>n;
while(n--){
ans=0;
int x,y;
cin>>x>>y>>s3;
int l1=s3.length();
string s4=s2.substr(x,y-x+1);
string s5;
for(j=0;j<(y-x+1);j++)
{
if(j+l1<=(y-x+1))
{
string s5=s4.substr(j,l1);
if(s5==s3) ans++;
}
}
cout<<ans<<endl;
}
}
return 0;
}