申請SAE

如果您發現本博客的外觀很難看,那是因為部分外觀文件被中國.國家.防火.牆屏.蔽所致!
請翻~牆!

我的Wordpress博客的地址: http://zhuyf.tk/
顯示具有 字符串 標籤的文章。 顯示所有文章
顯示具有 字符串 標籤的文章。 顯示所有文章

2012年2月4日 星期六

【搜索】單詞遊戲 words 解題報告

Title: 單詞遊戲
Input: words.in
Output: words.out
Time Limit: 1000 ms
Memory Limit: 128 MB
Level: ★☆
【問題描述】
慧慧和南南在玩一個單詞遊戲。
他們輪流說出一個僅包含母音字母的單詞,並且後一個單詞的第一個字母必須與前一個單詞的最後一個字母一致。
遊戲可以從任何一個單詞開始。
任何單詞禁止說兩遍,遊戲中只能使用給定詞典中含有的單詞。
遊戲的複雜度定義為遊戲中所使用的單詞長度總和。
編寫程序,求出使用一本給定的詞典來玩這個遊戲所能達到的遊戲最大可能複雜度。

2012年2月3日 星期五

【動態規劃】IOI2000 回文詞

Title: 回文詞
Input: palin.in
Output: palin.out
Time Limit: 1000 ms
Memory Limit: 128 MB
Level: ★☆
【问题描述】
    迴文詞是一種對稱的字元串——也就是說,一個迴文詞,從左到右讀和從右到 左讀得到的結果是一樣的。任意給定一個字元串,通過插入若干字元,都可以變成一個迴文 詞。你的任務是寫一個程序,求出將給定字元串變成迴文詞所需插入的最少字元數。 比如字元串“Ab3bd”,在插入兩個字元後可以變成一個迴文詞(“dAb3bAd” “Adb3bdA”)。然而,插入兩個以下的字元無法使它變成一個迴文詞。

網易2010“有道難題”編程挑戰賽 有道搜索框

描述 Description
在有道搜索框中,當輸入一個或者多個字符時,搜索框會出現一定數量的提示,如下圖所示:

現在給你N個單詞和一些查詢,請輸出提示結果,爲了簡這個問題,只需要輸出以查詢詞爲前綴的並且按字典序排列的最前面的8個單詞,如果符合要求的單詞一個也沒有請只輸出當前查詢詞。 

2012年2月2日 星期四

USACO Feb07 奶牛詞典 Cow Lexicon

Title: 奶牛詞典
Input: lexicon.in
Output: lexicon.out
Time Limit: 1000 ms
Memory Limit: 128 MB
Level: ★★
譯: zqzas

題目描述:

沒有幾個人知道,奶牛有她們自己的字典,裡面的有W (1 ≤ W ≤ 600)個詞,每個詞的長度不超過25,且由小寫字母組成.她們在交流時,由於各種原因,用詞總是不那麼準確.比如,貝茜聽到有人對她 說"browndcodw",確切的意思是"browncow",多出了兩個"d",這兩個"d"大概是身邊的噪音.

奶牛們發覺辨認那些奇怪的資訊很費勁,所以她們就想讓你幫忙辨認一條收到的消息,即一個只包含小寫字母且長度為L (2 ≤ L ≤ 300)的字元串.有些時候,這個字元串裡會有多餘的字母,你的任務就是找出最少去掉幾個字母就可以使這個字元串變成準確的"牛語"(即奶牛字典中某些詞 的一個排列).



2012年1月31日 星期二

[經典算法]字符串的排序 (tyvj 1101)

試題:tyvj 1101  (http://tyvj.cpwz.cn/Problem_Show.asp?id=1101)

【題目大意】
給你N(N<=10000)字符串,每個字符串長度小於256,把他們按字典序排序並輸出。

【分析】
C++的快排不是用來吃白飯的~直接調用C++的快排函數,0 ms 無壓力。
為什麼還有很多人會超時啊~




VijosNT Mini 2.0.5.6

#01: Accepted (0ms, 1212KB)
#02: Accepted (0ms, 1036KB)
#03: Accepted (0ms, 1192KB)
#04: Accepted (0ms, 880KB)
#05: Accepted (0ms, 1020KB)
#06: Accepted (0ms, 760KB)
#07: Accepted (0ms, 528KB)
#08: Accepted (0ms, 452KB)
#09: Accepted (0ms, 584KB)
#10: Accepted (0ms, 1084KB)

Accepted / 100 / 0ms / 1212KB

2012年1月28日 星期六

[字典樹]OI練習題:詞鏈 link 解題報告

Title: 詞鏈【傳送門】
Input: link.in
Output: link.out
Time Limit: 1000 ms
Memory Limit: 128 MB
Level: ★☆
【問題描述】
給定一個僅包含小寫字母的英文單詞表,其中每個單詞最多包含 50 個字母。
如果一張由一個詞或多個片語成的表中,每個單詞(除了最後一個)都是排在它後面的單詞的前綴,則稱此表為一個詞鏈。例如下面的單片語成了一個詞鏈:
i
int
integer
而下面的單詞不組成詞鏈:
integer
intern
請在給定的單詞表中取出一些詞,組成最長的詞鏈。最長的詞鏈就是包含單詞數最多的詞鏈。
資料保證給定的單詞表中,單詞互不相同,並且單詞按字典順序排列。

2011年12月26日 星期一

[並查集]HAOI 破譯密文 encrypt 解題報告

【題目描述】  查看題目
原文鏈接:http://yeefan.tk/blog/haoi-encrypt/
資訊的明文是由0利1組成的非空序列。但在網絡通信中,為了資訊的安全性,常對明文進行加密,用密文進行傳輸。密文是由0、1和若干個密碼字母組成,每個密碼字母代表不同的01串,例如,密文二011a0bf00a01。密碼破譯的關鍵是確定每個密碼的含義。
經過長期統計分析,現在知道了每個密碼的固定長度,如今,我方又截獲了敵方的兩段密文S1和S2,並且知道S1二S2,即兩段密文代表相同的明文。你的任務是幫助情報人員對給定的兩段密文進行分析,看一看有多少種可能的明文。
【輸入文件】
第1行: S1 (第1段密文)
第2行: S2 (第2段密文)
第3行: N (密碼總數, N<=26)
第4—N+3行: 字母i 長度i (密碼用小寫英文字母表示, 密碼長度<=100)

【輸出文件】
M(表示有M種可能的明文)

【輸入輸出樣例】
encrypt.in
100ad1
cc1
4
a 2
d 3
c 4
b 50
encrypt.out
2
【約束條件】
明文的長度<=10000

【分析】
既然每個密文代表一段明文,那我們可以把密文展開
如樣例的:
100ad1
cc1
4
a 2
d 3
c 4
b 50
我們就可以展開成
1 0 0 a1 a2 d1 d2 d3 1
c1 c2 c3 c4 c1 c2 c3 c4 1
那麼問題就成了在這麼一串數中找出有多少個數不定集合.
即c1代表1 c2代表0 c3代表0
但是 c4和a1共同代表什麼呢,這是問題的關鍵,這就用到了並查集:
首先 1 0 a1 a2…d2 d3都是獨立的集合
從i=1開始向右掃描
先把1所在的集合和c1所在的集合歸成一類,
0所在的集合和c2所在的集合歸成一類
….
最後一定是
代表0的字母有一個集合
代表1的字母有一個集合
不能確定代表什麼的有x個集合
因為每個集合代表的數字要麼是1要麼是0有兩種情況
所以兩個集合有4種情況
三個集合有8種情況
x個集合有2^x種情況
所以我們只需要用並查集算出有幾個非0或1的集合,再累乘後輸出即可
注意:有一個密文既對應0也對應1,這種情況構不成任何正確的明文,所以應當輸出0。

【我的代碼】
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
using namespace std;
int num[30];
 
const char base='a'-1;
const int MAXN=3000;
int Letter[30];//每個密碼的密碼長度
int Num[30][102];
char S1[105];
char S2[105];
int N;//密碼總數
int T=0;//不定集合的數量
int Sum=0;//最終結果
int M=0;
int DealA[MAXN]={0};
int DealB[MAXN]={0};
int Num0;
int Num1;
int Len=0;
 
class Node
{
public:
 int parent;
 int count;
}UFS[MAXN];
 
void UFS_Init(int i)
{
 UFS[i].count=1;
 UFS[i].parent=i;
}
 
int UFS_Find(int x)
{
 int i=x;
 while(i!=UFS[i].parent)
  i=UFS[i].parent;
 
 int j=x;
 while(j!=i)
 {
  int tmp=UFS[j].parent;
  UFS[j].parent=i;
  j=tmp;
 }
 return i;
}
 
void UFS_Merge(int x,int y)
{
 x=UFS_Find(x);
 y=UFS_Find(y);
 if(x==y)
  return;
 
 if(UFS[x].count>UFS[y].count)
 {
  UFS[y].parent=x;
  UFS[x].count+=UFS[y].count;
 }
 else
 {
  UFS[x].parent=y;
  UFS[y].count+=UFS[x].count;
 }
}
 
void init()
{
 scanf("%s\n%s\n",&S1,&S2);
 scanf("%d\n",&N);
 memset(Letter,0,sizeof(Letter));
 char cTmp;
 int iTmp;
 for (int i=1;i<=N;i++)
 {
  scanf("%c %d\n",&cTmp,&iTmp);
  Letter[cTmp-base]=iTmp;
 } 
 
 for(int i=1;i<=26;i++)
 {
  for (int j=1;j<=Letter[i];j++)
  {
   M++;
   Num[i][j]=M;
   UFS_Init(M);
  }
 }
 
 M++;
 Num0=M;
 UFS_Init(M);
 
 M++;
 Num1=M;
 UFS_Init(M);
 
 int top=0;
 for (unsigned int i=0;i<strlen(S1);i++)
 {
  if(isalpha(S1[i]))
  {
   for (int j=1;j<=Letter[ S1[i]-base ]; j++)
   {
    top++;
    DealA[top]=Num[S1[i]-base][j];
   }
  }
  else
  {
   if(S1[i]=='0')
   {
    top++;
    DealA[top]=Num0;
   }
   else
   {
    top++;
    DealA[top]=Num1;
   }
  }
 }
 
 Len=top;
 top=0;
 for (unsigned int i=0;i<strlen(S2);i++)
 {
  if(isalpha(S2[i]))
  {
   for (int j=1;j<=Letter[ S2[i]-base ]; j++)
   {
    top++;
    DealB[top]=Num[S2[i]-base][j];
   }
  }
  else
  {
   if(S2[i]=='0')
   {
    top++;
    DealB[top]=Num0;
   }
   else
   {
    top++;
    DealB[top]=Num1;
   }
  }
 } 
}
 
int work()
{
 for(int i=1;i<=Len;i++)
 {
  UFS_Merge(DealA[i],DealB[i]);
 }
 
 if(UFS_Find(Num0)==UFS_Find(Num1))
 {
  return 0;
 }
 
 bool Used[MAXN];
 memset(Used,0,sizeof(Used));
 
 int Find_Num0=UFS_Find(Num0);
 int Find_Num1=UFS_Find(Num1);
 for(int i=1;i<=Len;i++)
 { 
  int tmp=UFS_Find(DealA[i]);
  if(tmp==Find_Num0 || tmp==Find_Num1 || Used[tmp])
   continue;
 
  T++;
  Used[tmp]=true;
 }
 
 for(int i=1;i<=Len;i++)
 {
  int tmp=UFS_Find(DealB[i]);
  if(tmp==Find_Num0 || tmp==Find_Num1 || Used[tmp])
   continue;
 
  T++;
  Used[tmp]=true;
 }
 
 Sum=1;
 for (int i=1;i<=T;i++)
  Sum*=2;
 return Sum;
}
 
int main()
{
 freopen("encrypt.in","r",stdin);
 freopen("encrypt.out","w",stdout);
 init();
 printf("%d\n",work());
 return 0;
}

2011年12月11日 星期日

[動態規劃]OI練習題:乘法問題 [chf] 解題報告


【問題描述】
設有一個長度為 N 的數字字元串,分成 K+1 個部分,使得 K+1 個部 分的乘積最大。 例如 N=6 ,且數字字元串為 ‘ 310143 ‘ , K=3. 此時可能有的情況有以 下各種:
3 * 1 * 0 * 143=0
3 * 1 * 01 * 43=129
3 * 1 * 014 * 3=126
3 * 10 * 1 * 43=1290
3 * 10 * 14 * 3=1260
3 * 101 * 4 * 3=3636
31 * 0 * 1 * 43=0
31 * 01 * 4 * 3=372
310 * 1 * 4 * 3=3720
問題:當 N ,數字串, K 給出之後,找出一種分法使其乘積最大。
【輸入格式】
輸入由兩行組成,第一行有兩個整數,n(1≤n≤30)、k(1≤n≤30);n表示數字串長度、k表示乘號

個數。第二行是數字串。
【輸出格式】
輸出為一個整數,為乘積最大值。
【輸入樣例】
輸入文件名:chf.in
9 4
321044105
輸出文件名:chf.out
5166000
【分析】
動態規劃,和『NOIP2001 乘積最大』一樣。
狀態設定:
F[i,j]:前i個數字添加j個乘號時的最大值。
Num[i,j]:第i的數到第j個的數組成的數,可以在DP前用一個O(N^2)的預處理求出。
狀態轉移方程:
F[i,j]=Max(F[k,j-1]*Num[k+1][i])  (1<=k<=i-1)
目標狀態:  F[N,K]
時間複雜度:O(2*N^2)

【我的代碼】


#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; typedef long long LL; LL N,K; LL num[100][100]; LL F[100][100];   LL Max(LL a,LL b) { if (a>=b) return a; return b; }   LL myatoi(char *str) { LL ret=0; LL sign=1; if(*str=='-') sign=-1; else ret=ret*10+(*str-'0'); str++;   while(*str!= '\0') { ret=ret*10+(*str-'0'); str++; } return sign*ret; }   void init() { cin>>N>>K; char Temp[100]; cin>>Temp; char tmp[100]; for (unsigned int i=1;i<=strlen(Temp);i++) { for (unsigned int j=i;j<=strlen(Temp);j++) { unsigned int ti=i-1; unsigned int tj=j-1; memset(tmp,'\0',sizeof(tmp)); for (unsigned int k=ti;k<=tj;k++) tmp[k-ti]=Temp[k]; num[i][j]=myatoi(tmp); } } }   void dp() { for (int i=1;i<=N;i++) F[i][0]=num[1][i]; for (int j=1;j<=K;j++) { for (int i=1;i<=N;i++) { F[i][j]=0; for (int k=1;k<=i-1;k++) F[i][j]=Max(F[i][j],F[k][j-1]*num[k+1][i]); } } cout<<F[N][K]<<endl; }   int main() { freopen("chf.in","r",stdin); freopen("chf.out","w",stdout); init(); dp(); return 0; }

2011年11月28日 星期一

GZOI2011廣州NOI省選:簡易計算器 calculator 解題報告

【問題描述】相信大家都用過計算器,一般來說,計算機都可以計算簡單的加、減、乘、除這幾種運算。簡易計算器的功能和一般的計算器一樣,只是它更加簡單,只能處理整數運算,也就是說,它沒有小數點按鈕,並且它的除法運算是整除運算。現在,我們給出簡易計算器上的按鈕序列,請你編程序,模擬簡易計算器的功能,輸出最終的結果。
      
【計算器組成】簡易計算器由以下按鈕組成:數字按鈕: 0 1 2 3 4 5 6 7 8 9運算按鈕: + - * /等於號按鈕:=正負轉換按鈕:+/-為了表述方便,+/- 按鈕用 F 表示 ,
 
【計算器邏輯處理】
    
計算器內存有3個值,M1,M2,OP,STM1為計算器的左運算值,初始值為0M2為計算器的右運算值,初始值0OP為計算器的當前運算符,初始值為空ST為狀態標記,初始值為0
 
狀態裝換邏輯如下:
 
ST=0 (M1/OP輸入態):顯示值:M1
 
輸入數字N :M1=N ,轉 ST=1狀態
 
輸入F :M1=-M1,轉 ST=0狀態
 
輸入運算符:OP=運算符,轉ST=2狀態
 
輸入“=”:轉 ST=0狀態
 
ST=1 (M1+/OP輸入態):顯示值:M1
 
輸入數字N :如果M1>=0則 M1=M1*10+N 否則M1=M1*10-N;轉 ST=1狀態;
 
輸入F :M1=-M1,轉 ST=1狀態;
 
輸入運算符:OP=運算符,轉ST=2狀態
 
輸入“=”:轉 ST=0狀態
 
ST=2 (OP/M2輸入態):顯示值:M1
 
輸入數字N:M2=N,轉ST=3狀態;輸入F:M2=0,轉 ST=3狀態;
 
輸入運算符:OP=運算符,轉ST=2狀態
 
輸入“=”:
 
轉 ST=0狀態
 
ST=3 (M2+/OP輸入態):顯示值:M2
 
輸入數字N:如果M2>=0則 M2=M2*10+N 否則M2=M2*10-N;轉ST=3狀態;輸入F:M2=-M2,轉 ST=3狀態;
 
輸入運算符:M1=[M1][OP][M2] 的值OP=運算符;轉ST=2狀態
 
輸入“=”: M1=[M1][OP][M2] 的值轉ST=0狀態
 
【輸入格式】輸入只有一行,表示在計算器輸入的按鈕,長度<=100,裡面只包含如下字符 :0123456789+-*/=F輸入數據保證不會出現除以0的情況,運算過程中各個內存的值的範圍在[-10000000, 10000000] 以內

 
【輸出格式】
    
輸出包含一行整數,表示最後在計算器顯示的結果
 
【輸入樣例】
        
123=*2F-+/3+-=
        
【輸出樣例】
 
-82


 【分析】
字符串處理題目,由於各種狀態之間的來回跳換,所以用遞歸實現比較方便。由於數據不大,暴力的遞歸不成問題。

時間複雜度:O(length)。
            length表示字符串的長度。


 【我的代碼】
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
char str[102];
int OP;
int top=0;
int M1=0,M2=0;
int show;
int len;
int tmp;
void deal0();
void deal1();
void deal2();
void deal3();

int Getop(char op)
{
    if(op=='+')
        return 1;
    if(op=='-')
        return 2;
    if(op=='*')
        return 3;
    if(op=='/')
        return 4;
    if(op=='F')
        return 5;
    if(op=='=')
        return 6;
    return 0;
}

void check()
{
    if(top==len)
    {
        printf("%d\n",show);
        exit(0);
    }
    return;
}

void deal0()
{
    show=M1;
    check();
    tmp=0;
    if(Getop(str[top])==0)
    {
        while(Getop(str[top])==0 &&top<len)
        {
            tmp=tmp*10+str[top]-'0';
            top++;
        }
        M1=tmp;
        deal1();
        return;
    }
    if(Getop(str[top])==5)
    {
        M1=-M1;
        top++;
        deal0();
        return;
    }
    if(Getop(str[top])>=1 && Getop(str[top])<=4)
    {
        OP=Getop(str[top]);
        top++;
        deal2();
        return;
    }
    if(Getop(str[top])==6)
    {
        top++;
        deal0();
        return;
    }
}

void deal1()
{
    show=M1;
    check();
    tmp=0;
    if(Getop(str[top])==0)
    {
        while(Getop(str[top])==0 && top<len)
        {
            tmp=tmp*10+str[top]-'0';
            top++;
        }
        if(M1>=0)
            M1=M1*10+tmp;
        else
            M1=M1*10-tmp;
        deal1();
        return;
    }
    if(Getop(str[top])==5)
    {
        M1=-M1;
        top++;
        deal1();
        return;
    }
    if(Getop(str[top])>=1 && Getop(str[top])<=4)
    {
        OP=Getop(str[top]);
        top++;
        deal2();
        return;
    }
    if(Getop(str[top])==6)
    {
        top++;
        deal0();
        return;
    }
}

void deal2()
{
    show=M1;
    check();
    tmp=0;
    if(Getop(str[top])==0)
    {
        while(Getop(str[top])==0 && top<len)
        {
            tmp=tmp*10+str[top]-'0';
            top++;
        }
        M2=tmp;
        deal3();
        return;
    }
    if(Getop(str[top])==5)
    {
        M2=0;
        top++;
        deal3();
        return;
    }
    if(Getop(str[top])>=1 && Getop(str[top])<=4)
    {
        OP=Getop(str[top]);
        top++;
        deal2();
        return;
    }
    if(Getop(str[top])==6)
    {
        top++;
        deal0();
        return;
    }
}

void deal3()
{
    show=M2;
    check();
    tmp=0;
    if(Getop(str[top])==0)
    {
        while(Getop(str[top])==0 && top<len)
        {
            tmp=tmp*10+str[top]-'0';
            top++;
        }
        if(M2>=0)
            M2=M2*10+tmp;
        else
            M2=M2*10-tmp;
        deal3();
        return;
    }
    if(Getop(str[top])==5)
    {
        M2=-M2;
        top++;
        deal3();
        return;
    }
    if(Getop(str[top])>=1 && Getop(str[top])<=4)
    {
        if(OP==1)
            M1=M1+M2;
        if(OP==2)
            M1=M1-M2;
        if(OP==3)
            M1=M1*M2;
        if(OP==4)
            M1=M1/M2;
        OP=Getop(str[top]);
        top++;
        deal2();
        return;
    }
    if(Getop(str[top])==6)
    {
        top++;
        //deal0();
        if(OP==1)
            M1=M1+M2;
        if(OP==2)
            M1=M1-M2;
        if(OP==3)
            M1=M1*M2;
        if(OP==4)
            M1=M1/M2;
        deal0();
        return;
    }
}

void init()
{
    std::ios::sync_with_stdio(false);
    scanf("%s\n",&str);
    len=strlen(str);
    return;
}

int main()
{
    freopen("calculator.in","r",stdin);
    freopen("calculator.out","w",stdout);
    init();
    deal0();
    return 0;
}
 

 
 【評測結果】

正在连接评测机...

已连接到评测机
GRID 1
名称 Flitty
系统版本 1.00
备注 COGS 1号评测机 Flitty
正在编译...
编译成功

测试点 结果 得分 运行时间 内存使用 退出代码
1 正确 20 0.000 s 275 KB 0
2 正确 20 0.000 s 275 KB 0
3 正确 20 0.000 s 275 KB 0
4 正确 20 0.000 s 275 KB 0
5 正确 20 0.000 s 275 KB 0
运行完成
运行时间 0.002 s
平均内存使用 275 KB
测试点通过状况 AAAAA
得分:100
恭喜你通过了全部测试点!

2011年11月26日 星期六

NOIP2011普及組 複賽 解題報告

pdf試題下載
1.數字反轉 reverse
【問題描述】
給定一個整數,請將該數各個位上數字反轉得到一個新數。新數也應滿足整數的常見形式,即除非給定的原數爲零,否則反轉後得到的新數的最高位數字不應爲零(參見樣例2)。
【輸入】
輸入文件名爲reverse.in。
輸入共1 行,一個整數N。
【輸出】
輸出文件名爲reverse.out。
輸出共1 行,一個整數,表示反轉後的新數。
【輸入輸出樣例1】
reverse.in
123
reverse.out
321
【輸入輸出樣例2】
reverse.in
-380
reverse.out
-83
【數據範圍】
-1,000,000,000 ≤ N≤ 1,000,000,000。

【分析】
普及組的水題,直接模擬即可。
注意:
   1.讀入時用字符串讀入。
   2.注意輸入“0”的情況。

【我的代碼】
C++语言: Codee#24218
//NOIP2011_Junior_reverse
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int main()
{
    freopen("reverse.in","r",stdin);
    freopen("reverse.out","w",stdout);
    char line[100]={'\0'};
    scanf("%s\n",&line);
    int s=0;
    int len=strlen(line);
    len--;
    if(line[0]=='0')
        printf("0\n");
    else
    {
        if(line[0]=='-')
        {
            s++;
            printf("-");
        }
        while(line[len--]=='0');
        for (int i=len+1;i>=s;i--)
            printf("%c",line[i]);
        printf("\n");
    }
    return 0;
}


【評測結果】

正在连接评测机...

已连接到评测机
GRID 1
名称 Flitty
系统版本 1.00
备注 COGS 1号评测机 Flitty
正在编译...
编译成功

测试点 结果 得分 运行时间 内存使用 退出代码
1 正确 10 0.000 s 273 KB 0
2 正确 10 0.000 s 273 KB 0
3 正确 10 0.000 s 273 KB 0
4 正确 10 0.000 s 273 KB 0
5 正确 10 0.000 s 273 KB 0
6 正确 10 0.000 s 273 KB 0
7 正确 10 0.000 s 273 KB 0
8 正确 10 0.000 s 273 KB 0
9 正确 10 0.000 s 273 KB 0
10 正确 10 0.000 s 273 KB 0
运行完成
运行时间 0.003 s
平均内存使用 273 KB
测试点通过状况 AAAAAAAAAA
得分:100
恭喜你通过了全部测试点!

2.統計單詞數 stat
【問題描述】
一般的文本編輯器都有查找單詞的功能,該功能可以快速定位特定單詞在文章中的位置,有的還能統計出特定單詞在文章中出現的次數。
現在,請你編程實現這一功能,具體要求是:給定一個單詞,請你輸出它在給定的文章中出現的次數和第一次出現的位置。注意:匹配單詞時,不區分大小寫,但要求完全匹配,即給定單詞必須與文章中的某一獨立單詞在不區分大小寫的情況下完全相同(參見樣例1),如果給定單詞僅是文章中某一單詞的一部分則不算匹配(參見樣例2)。
【輸入】
輸入文件名爲stat.in,2 行。
第1 行爲一個字符串,其中只含字母,表示給定單詞;
第2 行爲一個字符串,其中只可能包含字母和空格,表示給定的文章。
【輸出】
輸出文件名爲stat.out。
只有一行,如果在文章中找到給定單詞則輸出兩個整數,兩個整數之間用一個空格隔開,分別是單詞在文章中出現的次數和第一次出現的位置(即在文章中第一次出現時,單詞首字母在文章中的位置,位置從0 開始);如果單詞在文章中沒有出現,則直接輸出一個整數-1。
【輸入輸出樣例1】
stat.in
To
to be or not to be is a question
stat.out
2 0
【輸入輸出樣例1 說明】
輸出結果表示給定的單詞To 在文章中出現兩次,第一次出現的位置爲0。
【輸入輸出樣例2】
stat.in
to
Did the Ottoman Empire lose its power at that time
stat.out
-1
【輸入輸出樣例2 說明】
表示給定的單詞to 在文章中沒有出現,輸出整數-1。
【數據範圍】
1 ≤ 單詞長度≤ 10。
1 ≤ 文章長度≤ 1,000,000。
 【分析】
這是NOIP2011複賽普及組中的第二道字符串處理題了~
讀入時都把大寫字母轉換成小寫,以方便判斷。
然後就很簡單了,直接暴力枚舉即可。
如果是string類,則之間用“=”號判等;如果是char型數組,用strcmp函數判等。


注意:
1.文章中空格有可能不止1個,要加以判斷。
2.只有strcmp函數返回0時才表示兩個字符數組相等。

【我的代碼】
C++语言: Codee#24217
//NOIP2011_Junior_stat
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
int main()
{
    freopen("stat.in","r",stdin);
    freopen("stat.out","w",stdout);
    char str[11];
    memset(str,'\0',sizeof(str));
    int len;
    cin>>str;
    len=strlen(str);
    for (int i=0;i<len;i++)
        str[i]=tolower(str[i]);
  
    string art;
    char tmp[1000001]={'\0'};
    int pos=-1;
    int tot=0;
    int tl;
    getline(cin,art);
    getline(cin,art);
    tl=art.length();
    for (int i=0;i<tl;i++)
        tmp[i]=art[i];
  
    int i=0;
    while(i<tl)
    {
        if(isalpha(tmp[i]))
        {
            int j=i;
            int k=0;
            char arr[1001]={'\0'};
            while(isalpha(tmp[j]))
            {
                arr[k]=tolower(tmp[j]);
                k++;
                j++;
            }
          
            if(strcmp(str,arr)==0)
            {
                tot++;
                if(pos==-1)
                    pos=i;
            }
            i=j+1;
        }
        else
            i++;
    }
  
    if(tot!=0)
        cout<<tot<<" "<<pos<<endl;
    else
        cout<<-1<<endl;
    return 0;
}



【評測結果】

正在连接评测机...

已连接到评测机
GRID 1
名称 Flitty
系统版本 1.00
备注 COGS 1号评测机 Flitty
正在编译...
编译成功

测试点 结果 得分 运行时间 内存使用 退出代码
1 正确 10 0.001 s 1172 KB 0
2 正确 10 0.001 s 1172 KB 0
3 正确 10 0.001 s 1172 KB 0
4 正确 10 0.001 s 1168 KB 0
5 正确 10 0.003 s 1168 KB 0
6 正确 10 0.018 s 1176 KB 0
7 正确 10 0.018 s 1172 KB 0
8 正确 10 0.169 s 1172 KB 0
9 正确 10 0.167 s 1172 KB 0
10 正确 10 0.167 s 1176 KB 0
运行完成
运行时间 0.547 s
平均内存使用 1172 KB
测试点通过状况 AAAAAAAAAA
得分:100
恭喜你通过了全部测试点!


3.瑞士輪 swiss
【背景】
在雙人對決的競技性比賽,如乒乓球、羽毛球、國際象棋中,最常見的賽制是淘汰賽和循環賽。前者的特點是比賽場數少,每場都緊張刺激,但偶然性較高。後者的特點是較爲公平,偶然性較低,但比賽過程往往十分冗長。
本題中介紹的瑞士輪賽制,因最早使用於1895 年在瑞士舉辦的國際象棋比賽而得名。
它可以看作是淘汰賽與循環賽的折衷,既保證了比賽的穩定性,又能使賽程不至於過長。

【問題描述】
2*N 名編號爲1~2N 的選手共進行R 輪比賽。每輪比賽開始前,以及所有比賽結束後,都會按照總分從高到低對選手進行一次排名。選手的總分爲第一輪開始前的初始分數加上已參加過的所有比賽的得分和。總分相同的,約定編號較小的選手排名靠前。
每輪比賽的對陣安排與該輪比賽開始前的排名有關:第1 名和第2 名、第3 名和第4名、……、第2K – 1 名和第2K 名、…… 、第2N – 1 名和第2N 名,各進行一場比賽。每場比賽勝者得1 分,負者得0 分。也就是說除了首輪以外,其它輪比賽的安排均不能事先確定,而是要取決於選手在之前比賽中的表現。
現給定每個選手的初始分數及其實力值,試計算在R 輪比賽過後,排名第Q 的選手編號是多少。我們假設選手的實力值兩兩不同,且每場比賽中實力值較高的總能獲勝。
【輸入】
輸入文件名爲swiss.in。
輸入的第一行是三個正整數N、R、Q,每兩個數之間用一個空格隔開,表示有2*N 名選手、R 輪比賽,以及我們關心的名次Q。
第二行是2*N 個非負整數s1, s2, …, s2N,每兩個數之間用一個空格隔開,其中si 表示編號爲i 的選手的初始分數。
第三行是2*N 個正整數w1, w2, …, w2N,每兩個數之間用一個空格隔開,其中wi 表示編號爲i 的選手的實力值。
【輸出】
輸出文件名爲swiss.out。
輸出只有一行,包含一個整數,即R 輪比賽結束後,排名第Q 的選手的編號。
【輸入輸出樣例】
swiss.in
2 4 2
7 6 6 7
10 5 20 15
swiss.out
1
【輸入輸出樣例說明】


本輪對陣 本輪結束後的得分
選手編號 / ① ② ③ ④
初始 / 7 6 6 7
第1 輪 ①—④ ②—③ 7 6 7 8
第2 輪 ④—① ③—② 7 6 8 9
第3 輪 ④—③ ①—② 8 6 9 9
第4 輪 ③—④ ①—② 9 6 10 9
【數據範圍】
對於30%的數據,1 ≤ N≤ 100;
對於50%的數據,1 ≤ N≤ 10,000;
對於100%的數據,1 ≤ N≤ 100,000,1 ≤ R≤ 50,1 ≤ Q≤ 2N,0 ≤ s1, s2, …, s2N ≤ 10^8,1 ≤ w1,
w2, …, w2N ≤ 10^8。

【分析】
這是普及組的一道難題。
首先,由於每輪比賽的次序都是由上一輪比賽完後的比分決定的,因此對於普及組的同學來說僅能使用模擬的方法來解決。容易想到的是每一輪模擬完以後快排一次,用這樣的方法,時間複雜度爲O(2Nlog2N*R),根據數據範圍可知這種思路僅能解決50%的數據。因此我們需要一種更有效的方式。
分析題意後可以發現,對於每一輪比賽過後,每一位選手都會有一種狀態,贏了或者輸了,而每一位選手比賽前都是有序的,那麼對於所有在該輪比賽中贏了或者是輸了的選手,都是有序的。即每輪比賽後,我們可以以O(N)的效率獲得勝負選手的有序隊列,對於兩組有序序列,容易想到將兩組數列歸併,歸併的效率爲O(N),這樣,完成一輪比賽的效率從O(2Nlog2N*R)縮減至O(NR),根據數據範圍,這樣的程序是能夠在1秒內出解的。

【我的代碼】
C++语言: Codee#24224
/*
*Problem:NOIP2011_Junior_Swiss 瑞士輪
*Author:Yee-fan Zhu
*School:Henan Experimental High School
*Method:Merge,QuickSort
*Date:2011.11.26
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
class SWISS
{
public:
    int num;
    int val;
    int tot;
}P[200003];
int N,R,Q;

SWISS A[100001],B[100001];
int pa,pb;

int cmp(const void *a,const void *b)
{
    class SWISS *c=(class SWISS *)a;
    class SWISS *d=(class SWISS *)b;
    if(c->tot!=d->tot)
        return d->tot-c->tot;
    return c->num-d->num;
}

void init()
{
    scanf("%d %d %d\n",&N,&R,&Q);
    N*=2;
    for(int i=1;i<=N;i++)
    {   
        P[i].num=i;
        scanf("%d",&P[i].tot);
    }
   
    for(int i=1;i<=N;i++)
        scanf("%d",&P[i].val);
    qsort(P+1,N,sizeof(SWISS),cmp);
}

void merge()
{
    int p=0;
    int i=1,j=1;
    while(i<=N/2&&j<=N/2)
    {
        if(A[i].tot>B[j].tot)
        {
            P[++p]=A[i++];
            continue;
        }
        if(A[i].tot==B[j].tot)
        {
            if(A[i].num<B[j].num)
            {   
                P[++p]=A[i++];
                continue;
            }
            P[++p]=B[j++];
            continue;
        }
        P[++p]=B[j++];
    }
    while(i<=N/2) P[++p]=A[i++];
    while(j<=N/2) P[++p]=B[j++];
}

void work()
{
    for (int i=1;i<=R;i++)
    {
        int j=1;
        pa=0,pb=0;
        while(j<N)
        {
            if(P[j].val>P[j+1].val)
                P[j].tot++,A[++pa]=P[j],B[++pb]=P[j+1];
            else
                P[j+1].tot++,A[++pa]=P[j+1],B[++pb]=P[j];
            j+=2;
        }
        merge();
    }
   
    qsort(P+1,N,sizeof(SWISS),cmp);
    printf("%d\n",P[Q].num);
}

int main()
{
    freopen("swiss.in","r",stdin);
    freopen("swiss.out","w",stdout);
    init();
    work();
    return 0;
}
【評測結果】
正在连接评测机...

已连接到评测机
GRID 1
名称 Flitty
系统版本 1.00
备注 COGS 1号评测机 Flitty
正在编译...
编译成功

测试点 结果 得分 运行时间 内存使用 退出代码
1 正确 10 0.000 s 4960 KB 0
2 正确 10 0.000 s 4960 KB 0
3 正确 10 0.001 s 4960 KB 0
4 正确 10 0.019 s 4960 KB 0
5 正确 10 0.047 s 4960 KB 0
6 正确 10 0.123 s 4960 KB 0
7 正确 10 0.254 s 4960 KB 0
8 正确 10 0.468 s 4960 KB 0
9 正确 10 0.543 s 4960 KB 0
10 正确 10 0.612 s 4960 KB 0
运行完成
运行时间 2.068 s
平均内存使用 4960 KB
测试点通过状况 AAAAAAAAAA
得分:100
恭喜你通过了全部测试点!