您的位置:首页 > 其它

【ASC44D】【观察找规律 语言模式识别】Detect Shuffling Method map 头文件识别+特殊关键词法 or 频率哈希法

2015-10-29 16:08 661 查看
头文件识别+特殊关键词法:
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<functional>
#include<string>
#include<algorithm>
#include<time.h>
#include<bitset>
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
typedef int Int;
template <class T> inline void gmax(T &a,T b){if(b>a)a=b;}
template <class T> inline void gmin(T &a,T b){if(b<a)a=b;}
using namespace std;
const int N=3e5,M=0,L=0,Z=1e9+7,maxint=2147483647,ms31=522133279,ms63=1061109567,ms127=2139062143;
int casenum,casei;
char s
,b[4];
int len,num;
int e[128];
bool block()
{
int rate=0;
int cnt;
MS(e,-1);
for(int i=0;i<len;i+=4)
{
for(int j=0;j<4;j++)e[s[i+j]]=i;

//#inc
if(e['#']==i)
{
cnt=0;
cnt+=e['i']==i;
cnt+=e['n']==i;
cnt+=e['c']==i;
if(cnt==3)return 1;//只要出现"#inc"就可以认定其必然是block
if(cnt==2)rate+=20;//如果3个中出现2个,加分[10,20]都是AC区间
continue;
}

//impo
cnt=0;
cnt+=e['i']==i;
cnt+=e['m']==i;
cnt+=e['p']==i;
cnt+=e['o']==i;
if(cnt==4)return 1;//只要出现"impo"就可以认定其必然是block

//int
cnt=0;
cnt+=e['i']==i;
cnt+=e['n']==i;
cnt+=e['t']==i;
if(cnt==3)rate+=2;

}
return rate>=60;
}
void fre(){freopen("detect.in","r",stdin);freopen("detect.out","w",stdout);}
int main()
{
fre();
scanf("%d",&casenum);getchar();
for(casei=1;casei<=casenum;casei++)
{
gets(s);
len=strlen(s);
num=len/4;
puts(block()?"block":"random");
}
return 0;
}
/*
【题意】 http://codeforces.com/gym/100518/attachments/download/2791/20132014-summer-petrozavodsk-camp-andrew-stankevich-contest-44-asc-44-en.pdf 给你一个代码长度为L(5kb~20kb)的c++或java程序S,它的长度L恰好为4的倍数。
我们会对这个代码做下列两种变换之一:
一,整体任意变换,使其完全无序化。
二,
1,先把S每4个字符划分成1段,共计划分为L/4段
2,再把这L/4段字符之间做整体的任意位置变换,
3,再把每段内部的字符做任意位置变换,
4,再总共做[L/10]次操作,每个操作交换任意两个位置的字符。

变换的次数为n(10<=n<=100且n为偶数)次。
每次都是基于S重新做的变换。
n次变换,有一半是变换1,另外一半是变换2。
让你判定每行的变换是变换1还是变换2。

如果对于80%以上的行都判定正确,那就可以AC这道题。

【类型】
观察找规律

【分析】
首先,要找到c++和java中比较特殊的标识符
c++是头文件,而且正常的程序都含有#include<>
于是我们判定一个块——
是否含有#inc的内部交换产物,
是否含有lude的内部交换产物。
给它们以一定的权重,然后判定是否block。
java的话就用impo来测吧。

再加上for( 和 (int,这道题就这样被我混过去了2333

【时间复杂度&&优化】
O(n)

本来自己的加分规则还判定了——
//lude
cnt=0;
cnt+=e['l']==i;
cnt+=e['u']==i;
cnt+=e['d']==i;
cnt+=e['e']==i;
if(cnt==4)return 1;//只要出现"lude"就可以认定其必然是block
if(cnt==3)rate+=2;//出现3个的话加分并不多

//for( && (int
if(e['(']==i)
{
cnt=0;
cnt+=e['f']==i;
cnt+=e['o']==i;
cnt+=e['r']==i;
if(cnt==4)return 1;//只要出现"for("就可以认定其必然是block
cnt=0;
cnt+=e['i']==i;
cnt+=e['n']==i;
cnt+=e['t']==i;
if(cnt==4)return 1;//只要出现"(int"就可以认定其必然是block
}

//for
cnt=0;
cnt+=e['f']==i;
cnt+=e['o']==i;
cnt+=e['r']==i;
if(cnt==3)rate+=2;

//.*;
cnt=0;
cnt+=e['.']==i;
cnt+=e['*']==i;
cnt+=e[';']==i;
if(cnt==3)rate+=20;//出现.*;也可以给定大量加分

然而实际上只要判定"#inc","impo"和"int"即可~~

【数据】
input
10
c<( { ldulm ca}; p itno, loerWdd"!oi t">fsntrielH ) % ", si#inn)("
! dtn"or #iis np "Woo ,% )lfn) {clr m>t(ud; tl<idsec la, H} (i "ne"i
l s,tdio( n)p l { };ud ,tirnlroWc <slH"etn # o ema %inic " >f"(i"!)d
i e nirr ai )pi(; d cnt ,l o s"n {"W,l>!" m Htt <o }("uil#s %)nd c fodle
H ";niorWloidtldue"!)d { n ()le" > plm ,t,rn aio s"ini#cs <c(%ft }
lWcu# eniaf(eo dn !>) "dtisd oni %n tr l" lt,i)mc H(; <} p" s,"r { ilo
idtolrWa> n <csm o " s,ledur it itn%"f(i#cnlH el ,o )"d! "{) (n ;} pi
lttdnri an" l# "ms o p>{i i ct r %o)osi ,nfHni!d "u;l (l cd" W}e(<),e
iencsc< !d ""ileW{ olo rldu# }; ) n (s ,"tin "(f% ptHrntoidl), ami >
nnod)plo{c #" n%(elcu ", t d t,s") ( iims nWl ;iiadt! r rf }i H> e "o<l

output
block
random
block
random
block
random
block
random
block
random
*/


频率哈希法:

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<functional>
#include<string>
#include<algorithm>
#include<time.h>
#include<bitset>
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
typedef int Int;
template <class T> inline void gmax(T &a,T b){if(b>a)a=b;}
template <class T> inline void gmin(T &a,T b){if(b<a)a=b;}
using namespace std;
const int N=105,M=3e5,L=0,Z=1e9+7,maxint=2147483647,ms31=522133279,ms63=1061109567,ms127=2139062143;
char s
[M],b[4];
map<string,int>mop;
pair<LL,int>a
;
bool ans
;
void fre()
{
freopen("detect.in","r",stdin);
freopen("detect.out","w",stdout);
}
int main()
{
fre();
int T;scanf("%d",&T);getchar();
for(int t=1;t<=T;t++)
{
gets(s[t]);
for(int i=0;s[t][i];i+=4)
{
for(int j=0;j<4;j++)b[j]=s[t][i+j];
sort(b,b+5);
++mop[b];
}
}
for(int t=1;t<=T;t++)
{
a[t].first=0;
a[t].second=t;
for(int i=0;s[t][i];i+=4)
{
for(int j=0;j<4;j++)b[j]=s[t][i+j];
sort(b,b+5);
a[t].first+=mop[b]*mop[b];
}
}
sort(a+1,a+T+1);
for(int i=1;i<=T/2;i++)ans[a[i].second]=0;
for(int i=T/2+1;i<=T;i++)ans[a[i].second]=1;
for(int i=1;i<=T;i++)puts(ans[i]?"block":"random");
return 0;
}
/*
【题意】 http://codeforces.com/gym/100518/attachments/download/2791/20132014-summer-petrozavodsk-camp-andrew-stankevich-contest-44-asc-44-en.pdf 给你一个代码长度为L(5kb~20kb)的c++或java程序S,它的长度L恰好为4的倍数。
我们会对这个代码做下列两种变换之一:
一,整体任意变换,使其完全无序化。
二,
1,先把S每4个字符划分成1段,共计划分为L/4段
2,再把这L/4段字符之间做整体的任意位置变换,
3,再把每段内部的字符做任意位置变换,
4,再总共做[L/10]次操作,每个操作交换任意两个位置的字符。

变换的次数为n(10<=n<=100且n为偶数)次。
每次都是基于S重新做的变换。
n次变换,有一半是变换1,另外一半是变换2。
让你判定每行的变换是变换1还是变换2。

如果对于80%以上的行都判定正确,那就可以AC这道题。

【类型】
观察找规律

【分析】
第二种做法是map哈希,非常妙。很多人和队伍竟然都不约而同地想到了这个做法。
就是先离线读入所有串,对于每个串,都按照长度为4做分组,并且对每个长度为4的串,都按照ASCII码排序使其有序,并用map记录频率。
接下来,每个串都统计其子串的出现频率之和,按照这个出现频率由大到小把所有串做排序。
前一半就是block,后一半就是random,充分利用题目信息,而且很难被数据卡,非常巧妙~~

这种方法可以累加频数,也可以累加频数的平方,但是频数是可达5000^3级别,要提防爆int哦

【数据】
input
10
c<( { ldulm ca}; p itno, loerWdd"!oi t">fsntrielH ) % ", si#inn)("
! dtn"or #iis np "Woo ,% )lfn) {clr m>t(ud; tl<idsec la, H} (i "ne"i
l s,tdio( n)p l { };ud ,tirnlroWc <slH"etn # o ema %inic " >f"(i"!)d
i e nirr ai )pi(; d cnt ,l o s"n {"W,l>!" m Htt <o }("uil#s %)nd c fodle
H ";niorWloidtldue"!)d { n ()le" > plm ,t,rn aio s"ini#cs <c(%ft }
lWcu# eniaf(eo dn !>) "dtisd oni %n tr l" lt,i)mc H(; <} p" s,"r { ilo
idtolrWa> n <csm o " s,ledur it itn%"f(i#cnlH el ,o )"d! "{) (n ;} pi
lttdnri an" l# "ms o p>{i i ct r %o)osi ,nfHni!d "u;l (l cd" W}e(<),e
iencsc< !d ""ileW{ olo rldu# }; ) n (s ,"tin "(f% ptHrntoidl), ami >
nnod)plo{c #" n%(elcu ", t d t,s") ( iims nWl ;iiadt! r rf }i H> e "o<l

output
block
random
block
random
block
random
block
random
block
random
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  codeforces 脑洞