1. 程式人生 > >【GDOI2016模擬3.10】習用之語

【GDOI2016模擬3.10】習用之語

題意

給定N個長度均為四的字串,問他們恰好有K個字母不同的字串有多少對(相同位置),其中字符集為0~9,a~z. n50000

分析

十分顯然一道題目,暴力N2嘛,優化起來很快。
我們考慮一種情況:有L個字元相同——注意並不是恰好——列舉其中不同的位置為P1...PL。這樣的話求有多少對就很方便了,這是誰都能想到的方法,隨便用點演算法把原來所有字串分成若干塊(比如排序~~~),每塊裡的字串都有指定位置上的字母相同,其他沒有指定的位置我們不管。若有X個塊,每個塊有Sizex個字串,那麼這種情況的對數就是sizex(sizex1)/2
這樣我們得到很多種情況的答案。很明顯,要恰好,就是容斥一下的問題了,由於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,最後沒時間了才緊張思考,按邏輯走,很快想通,思想也是十分簡單,除錯基本不用。
這道題浪費了大量時間做無用功,好的開端是成功的一半啊···