【GDOI2016模擬3.10】習用之語
阿新 • • 發佈:2019-02-12
題意
給定N個長度均為四的字串,問他們恰好有K個字母不同的字串有多少對(相同位置),其中字符集為0~9,a~z. n
分析
十分顯然一道題目,暴力
我們考慮一種情況:有L個字元相同——注意並不是恰好——列舉其中不同的位置為
這樣我們得到很多種情況的答案。很明顯,要恰好,就是容斥一下的問題了,由於K最大隻有4,所以明顯可以過。
程式碼
#include<cstdio>
#include<algorithm>
#include<iostream>
#define fo(i,j,k) for(i=j;i<=k;i++)
using namespace std;
const int N=50005;
struct rec
{
int a[4],cmp;
}b[N];
int a[N][4],n,dd,i,j,c[4],dur,tt,kx,q1,l,rt;
long long ans,asw[20],as;
char s[4];
bool cmp(rec a,rec b ){return a.cmp<b.cmp;}
int cmp1(rec a,rec b)
{
int i=0;
while (a.a[i]==b.a[i]&&i<3) i++;
return i;
}
int get(int x)
{
int i,j;
ans=0;
fo(i,1,n)
{
dur=0;
tt=-1;
fo(j,0,3)
if (c[j]!=-1)
{
dur=dur*36+a[i][j];
b [i].a[++tt]=a[i][j];
}
fo(j,0,3)
if (c[j]==-1)
{
dur=dur*36+a[i][j];
b[i].a[++tt]=a[i][j];
}
b[i].cmp=dur;
}
sort(b+1,b+1+n,cmp);
dur=1;
tt=0;
fo(i,2,n)
{
kx=cmp1(b[i],b[i-1]);
if (kx>=x)
dur++;
else
{
ans+=(long long)(dur)*(dur-1)/2;
dur=1;
}
}
ans+=(long long)(dur)*(dur-1)/2;
return ans;
}
int main()
{
scanf("%d%d\n",&n,&dd);
c[0]=c[1]=c[2]=c[3]=-1;
fo(i,1,n)
{
scanf("%s\n",s);
fo(j,0,3)
{
if (s[j]>='0'&&s[j]<='9')
a[i][j]=s[j]-'0';
else
a[i][j]=s[j]-'a'+10;
}
}
int d[17][5]={{0,0,0,0,0},{1,1,1,1,4},{1,1,1,-1,3},{1,1,-1,1,3},{1,-1,1,1,3},{-1,1,1,1,3},{1,1,-1,-1,2},{1,-1,1,-1,2},{1,-1,-1,1,2},{-1,1,1,-1,2},{-1,1,-1,1,2},{-1,-1,1,1,2},{1,-1,-1,-1,1},{-1,1,-1,-1,1},{-1,-1,1,-1,1},{-1,-1,-1,1,1},{-1,-1,-1,-1,0}};
//這是打情況表
fo(i,1,16)
{
fo(j,0,3) c[j]=d[i][j];
if (i==13)
{
i=i;
}
asw[i]=get(d[i][4]);
for(l=1;l<i;l++)
{
rt=0;
fo(j,0,3)
if (d[l][j]==d[i][j]&&d[l][j]==1)
rt++;
if (rt==d[i][j]&&d[l][j]>=d[i][j]+1)
asw[i]-=asw[l];
}
if (4-d[i][4]==dd)
as+=asw[i];
}
printf("%lld\n",as);
}
反思
這道題比賽的時候千辛萬苦,改了5遍終於對了,最後對拍錯了搞得我交題時還憂心忡忡。問題是很明顯的。
1,審題不嚴謹,條件看著看著忘了。
2,構思的時候十分馬虎,先想了演算法,就是排序維護一種情況,然而把它打出來了以後我居然還不是很瞭解這個東西是幹什麼的,三番五次改程式各種地方,還懷疑是維護的姿勢不對。
3,最後沒時間了才緊張思考,按邏輯走,很快想通,思想也是十分簡單,除錯基本不用。
這道題浪費了大量時間做無用功,好的開端是成功的一半啊···