NOIp 前N天做題

時光匆匆匆匆啊,離NOIp2015 只有不到一週了,我想想我好像什麼都不知道啊,啊啊啊啊啊啊啊怎麼辦。。。。
我還是好好分析下這幾天的模擬題吧。

分數化小數

【題目描述】
寫一個程序,輸入一個形如N/D的分數(N是分子,D是分母),輸出它的小數形式。如果小數有循環節的話,把循環節放在一對括號中,例如:
1/3=33333333 寫成0.(3)
41/333=0.123123123… 寫成0.(123)
用xxx.0表示整數
典型的轉化例子:
1/3=0.(3)
22/5=4.4
1/7=0.(142857)
2/2=1.0
3/8=0.375
45/56=0.803(571428)
【輸入格式】
單獨的一行包括被空格分開的N和D,1≤N,D≤100000。
【輸出格式】
輸出一行,小數的表示方法上面已經說得很明白了。
【樣例輸入】
45 56
【樣例輸出】
0.803(571428)

分析:
拿到這一個題 分析 分析
模擬模擬一定是模擬 找一個分數值
先找到整數部分,然後按除法該怎麼算就怎麼模擬。
然後判斷一下各種情況。
最後一個問題就是 循環在哪(我們都知道一個有理數must能寫成分數形式 反之一樣)所以一定有。而當算除法剩下的那個數(餘數)與前面相同時is the answer。

就素這樣
順便背背讀入優化…..其實沒用

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

int read(){
 int x=0,f=1;char ch=getchar();
 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
 return x*f;
}

void init()
{ freopen("fracdec.in","r",stdin);
  freopen("fracdec.out","w",stdout);  
}

int n,d;// n/d
int itg,mo,xs[100000],ys[100000],lens;
int main(){
    init();
    bool flag=0;
    n=read();d=read();
    itg = n/d;
    mo=n-itg*d;
    int len=1;
    if(mo == 0)
    {
    printf("%d.0",itg);
    return 0;
    }
    else {
      while(len<100000)
      {
      ys[len] = mo; 
      for(int i=1 ;i<len ;i++)
      {
        if(mo == ys[i]){
        lens = i; 
        flag = 1;
        break;}
        }
      mo*=10;
      xs[len] = mo/d;
      mo-=xs[len]*d;
      len++;
      if(flag ==1){
       printf("%d.",itg);
       for(int i=1 ;i<lens ;i++)
       printf("%d",xs[i]);
       printf("(");
       for(int i=lens;i<len-1;i++)
       printf("%d",xs[i]);
       printf(")");
       return 0;
      }
      if(mo == 0){
      printf("%d.",itg);
      for(int i=1 ;i<len ;i++)
      printf("%d",xs[i]);
      return 0;
      }
      }
      } 
 return 0;
}

覆蓋牆壁

這裏寫圖片描述

給定N,要求計算2*N的牆壁的覆蓋方法。由於結果很大,所以只要求輸出最後4位。例如2*13的覆蓋方法爲13465,只需輸出3465即可。如果答案少於4位,就直接輸出就可以,不用加0,如N=3時輸出5。

【輸出格式】
一個整數N(1≤N≤1000000),表示牆壁的長。

【輸出格式】
輸出覆蓋方法的最後4位,如果不足4位就輸出整個答案。

【樣例輸入】
13

【樣例輸出】
3465

分析:
額 一看到題 額 我先做下一題吧。。。。狀壓嗎 額 一直都不會額
額 dfs 暴力搜索 好主意 額 dfs 也學得差 暴力怎麼寫
要不亂搞打表……..
仔細讀完題 N 好大
一定是dp 遞推什麼的
恩恩 想想想想想
好的 我發現了
我們定義 個 dp[i][3] i 鋪到多少 0 上面沒鋪 2下面沒鋪 1鋪完了
轉移 如果智力不夠就畫畫圖………反正可以轉移
dp[i][0]=dp[i-2][1] +dp[i-2][2]
dp[i][1]=dp[i-2][1]+dp[i-1][1]+dp[i-1][0]+dp[i-2][2]
dp[i][2]=dp[i][0]+dp[i-1][1]

then code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int M= 10000;
void init()
{ freopen("wall.in","r",stdin);
  freopen("wall.out","w",stdout);  
}
int f[1000005][3];
int n;
int main(){
  init();
  scanf("%d",&n);
  f[0][1] = 1;
  for(int i=1 ;i<=n ;i++)
  { if(i-2>=0)f[i][0] += f[i-2][1]+f[i-2][2];
    f[i][1] +=f[i-1][1]+f[i-1][0];
    if(i-2>=0)f[i][1] += f[i-2][1]+f[i-2][2];
    f[i][2] += f[i][0]+f[i-1][1];
    for(int j=0 ;j<=2;++j)
    f[i][j] %= M;
  }
  printf("%d",f[n][1]);
  return 0; 
}

獨木橋

【問題描述】
戰爭已經進入到緊要時刻。你是運輸小隊長,正在率領運輸部隊向前線運送物資。運輸任務像做題一樣無聊。你希望找些刺激,於是命令你的士兵們到前方的一座獨木橋上欣賞風景,而你留在橋下欣賞士兵們。士兵們十分憤怒,因爲這座獨木橋十分狹窄,只能容納一個人通過。假如有兩個人相向而行在橋上相遇,那麼他們兩人將無法繞過對方,只能由一個人回頭下橋,讓另一個人先通過。但是,可以有多個人同時呆在同一個位置。
突然,你收到從指揮部發來的信息,敵軍的轟炸機正朝着你所在的獨木橋飛來!爲了安全,你的部隊必須撤下獨木橋。獨木橋的長度爲L,士兵們只能呆在座標爲整數的位置,所有士兵的速度都爲1,當一個士兵某一時刻來到了座標爲0或L+1的位置時,他就離開了獨木橋。
每個士兵都有一個初始面對的方向,他們會以勻速朝着這個方向行走,中途不會自己改變方向。但是,如果兩個士兵面對面相遇,他們無法彼此通過對方,於是就分別轉身,繼續行走。轉身不需要任何時間。
由於先前的憤怒,你已不能控制你的士兵。甚至,你連每個士兵初始面對的方向都不知道。因此,你想要知道你的部隊最少需要多少時間就可能全部撤離獨木橋。另外,總部也在安排阻攔敵人的進攻,因此你還需要知道你的部隊最多需要多少時間才能全部撤離獨木橋。

【輸入文件】
第一行:一個整數L,表示獨木橋的長度。橋上的座標爲1..L
第二行:一個整數N,表示初始時留在橋上士兵的數目。
第三行:有N個整數,分別表示每個士兵的初始座標。初始時,沒有兩個士兵在同一座標。

【輸出文件】只有一行,輸出兩個整數,分別表示部隊撤離獨木橋的最小時間和最大時間。兩個整數用一個空格分開。

【樣例輸入】
4
2
1 3

【樣例輸出】
2 4

【數據規模及約定】
N≤L≤10000

沒記錯的話這是很經典的一類數學思考題
但是我做錯了………
額 好像跟螞蟻爬樹這種題很相似
恩 其實轉向什麼的想想知道根本不用管

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int M= 10000;

void init()
{ freopen("bridge.in","r",stdin);
  freopen("bridge.out","w",stdout);  
}
int n,l;
bool a[10005];

int main(){
  init();
  memset(a,0,sizeof(a));
  scanf("%d%d",&l,&n);
  if(n==0){
   printf("0 0");
   return 0;
  }
  for(int i=1 ;i<=n ;i++)
  { int x; 
    scanf("%d",&x);
    a[x] = 1;
  }

  int mid = l/2+1;
  int L=mid,R=mid;
  int ans,ans1=-9999,ans2=-9999;
  bool fl = 0,fr = 0;

  for(int i=mid ;i<=l;i++)
  {if(a[i]==1){ans1=l-i+1;break;}
  }
  for(int i=mid-1 ;i>=1 ;i--)
  {if(a[i]==1){ans2=i;break;}
  }
  ans = max(ans1,ans2);  

  int mans,mans1=-9999,mans2=-9999;
  for(int i=1 ;i<=l;i++)
  if(a[i]==1){mans1=l-i+1;
              break;}
  for(int i=l;i>=1 ;i--)
  if(a[i]==1){mans2=i;break;
  }
  mans = max(mans1,mans2);
  printf("%d %d",ans,mans);
  return 0;
}

分配小組

【問題描述】
有N個Mars人想要進行一項活動。他們需要分成幾個小組,每個人屬於其中一個小組。Mars人從出生起每個人就有一個印記,這個印記是個正整數。如果B的印記是A的倍數,那麼B就是A的父親,與地球人的定義不同,一個Mars人可以有多個父親。特別的,A不是自己的父親,但是所有其他與A的印記相同的人都是A的父親。因此,除了A自己,A的父親的父親都是A的父親。
Mars人十分強調子女的獨立,因此進行這項活動的分組時,任何人都不能和自己的父親分到同一小組。你的任務就是對於給定的N個Mars人,給出一種分組方案,使得小組的數量最少。顯然,這個問題一定存在可行解——你可以讓每個Mars人單獨一組。如果有多解,任意輸出一組即可。
【輸入文件】
第一行:一個整數N,表示Mars人的數量。
接下來一行有N個正整數,表示每個Mars人的印記。
【輸出文件】
只有一行是一個整數K,表示你分成的最少小組數量。

【樣例輸入】
5
1 1 3 1 5

【樣例輸出】
4

【樣例說明】
分組情況:
第1組:1
第2組:1
第3組:1
第4組:3 5
三個1必須各自分別分成一組;3和5不是倍數關係,可以分成一組。

【數據規模及約定】
N≤5000
1≤所有的印記≤5000
對於每個測試點,你給出的分組必須是合法的,且恰好和你的小組數量相等,否則本測試點得0分。
如果你給出的小組數量和標準答案相同,則本測試點得10分,否則本測試點得0分。

【樣例輸入2】
10
1 2 3 5 6 9 10 6 9 9
【樣例輸出2】
5

【樣例2說明】
分組:
第1組:1
第2組:2 3 5
第3組:6 9 10
第4組:6 9
第5組:9

讀完題 看看樣例大致也就懂了
也就是求一求要分成多少組 滿足每組裏面沒有數能被改組裏面的數整除。 這樣可以考慮一下是dp
dp[i]第i個數
先sort()小到大
然後只有可能是後面的數來%前面的數爲0;
所以if(a[i]%a[j]==0)dp[i] = max(dp[i],dp[j]+1)

大致是

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int M= 10000;

void init()
{ freopen("poset.in","r",stdin);
  freopen("poset.out","w",stdout);  
}

int n;
int a[5005];
int f[5005];
int ans=-99999;
int main(){
 init();
 scanf("%d",&n);
 for(int i=1 ;i<=n ;i++)
 {
   scanf("%d",&a[i]);
 }
 sort(a+1,a+n+1);

  for(int i=1 ;i<=n ;i++)f[i] = 1;

   for(int i=2 ;i<=n ;i++)
    for(int j=1 ;j<i ;j++)
     { 
       if(a[i]%a[j]==0) 
       f[i] = max(f[i] ,f[j]+1);
       ans = max(ans,f[i]);
       }     
 printf("%d",ans);
 return 0;  
}

我懶得去掉freopen了…..講究看。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章