申請SAE

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

我的Wordpress博客的地址: http://zhuyf.tk/

2011年10月27日 星期四

[數學遞推]OI練習題:Binacy

【題目描述】
求所有可以只用1和00拼成的長度爲N的二進制數的個數除以1 5746的餘數。
比如當N=4的時候,有5個可能的二進制:0011,0000,1001,1100,1111。
【輸入格式】
第一行一個正整數N
【輸出格式】
輸出所有可以只用1和00拼成的長度爲N的二進制數的個數除以15746的餘數。
【輸入樣例】
4
【輸出樣例】
5
【數據範圍】
在100%的數據中,1≤N<1000000

【分析】
先嘗試寫出前幾個,找找規律:
N=0時 結果為0
N=1時 結果為1
N=2時 結果為2
N=3時 結果為3
N=4時 結果為5
......
可以看出,這是斐波那契數列。

所以,只需要遞推出斐波那契數列即可。

遞推式:
               S[0]=0,S[1]=1,
               S[2]=2;
               S[n]=S[n-2]+S[n-1] (n>2)

【代碼】
這是我以前的代碼,不知道我當時為何要把前幾個數打成表。
#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
unsigned long long S[1000001];
int main()
{
    freopen("binacy.in","r",stdin);
    freopen("binacy.out","w",stdout);
    int N;
    cin>>N;
    if(N<=4)
    {
        switch(N)
        {
        case 0:
            cout<<0<<endl;
            break;
        case 1:
            cout<<1<<endl;
            break;
        case 2:
            cout<<2<<endl;
            break;
        case 3:
            cout<<3<<endl;
            break;
        case 4:
            cout<<5<<endl;
            break;
        }
        return 0;
    }
    S[3]=3;
    S[4]=5;
    for (int i=5;i<=N;i++)
        S[i]=(S[i-1]+S[i-2])%15746;
    cout<<S[N]<<endl;
    return 0;
}

2011年10月26日 星期三

位運算中 x&(-x) 的意義

 位運算中 x&(-x) 的意義是:
             把x的二進制表示中,除了最右邊的一個“1”留下,其他全部變成0後的十進制表達。

例如: 10&(-10)=?
    10的二進制表示的後4位為:1010,
   -10的二進制表示的後4位為:0110;
由於10的二進制表示中除了後四位以外均為0,-10的二進制表示中除了後四位以外都是1,所以這些數取“與”運算的結果都是0,不予考慮。
所以:1010與0110取“與”運算的結果就是:
                   0010,即2。


應用:
11&(-11)=1    => 11(base 10)=1011(base 2)  => 0001 =>1
12&(-12)=4    => 12(base 10)=1100(base 2)  => 0100 =>4

位運算中 x&(x-1)表達式的意義

請看下面的函數:

int func(int x)
{
    int countx = 0;
    while(x)
    {
        countx++;
        x = x&(x-1);
    }
    return countx;


假定x = 9999

則返回多少?

答案: 8

解析:9999的二進制的表示為10011100001111,看它的二進制表示中有幾個1。

其實這個函數的意義是統計X的二進制表示中1的個數。
 注: 每執行一次x = x&(x-1),會將x用二進制表示時最右邊的一個1變爲0,因爲x-1將會將該位(x用二進制表示時最右邊的一個1)變爲0。


【應用】
判斷一個數(x)是否是2的n次方
-------------------------------------
#include <stdio.h>

int func(int x)
{
    if( (x&(x-1)) == 0 )
        return 1;
    else
        return 0;
}

int main()
{
    int x = 8;
    printf("%d\n", func(x));
}
注:
(1) 如果一個數是2的n次方,那麼這個數用二進制表示時其最高位爲1,其餘位爲0。
(2) == 優先級高於 &

[基本練習][枚舉]OI練習題: 排序工作量 sortt

【問題描述】
Sort公司是一個專門爲人們提供排序服務的公司,該公司的宗旨是:“順序是最美麗的”。他們的工作是通過一系列移動,將某些物品按順序擺好。他們的服務是通過工作量來計算的,即移動東西的次數。所以,在工作前必須先考察工作量,以便向用戶提出收費數目。
用戶並不需要知道精確的移動次數,實質上,大多數人都是憑感覺來認定這一列物品的混亂程度,根據Sort公司的經驗,人們一般是根據“逆序對”的數目多少來稱呼這一序列的混亂程度。假設我們將序列中第I件物品的參數定義爲A[I],那麼,排序就是指將A數組從小到大排序。所謂“逆序對”是指目前A[1..N]中元素各不相同,若I<J且A[I]>A[j],則[I,J]就爲一個“逆序對”。
例如,數組<3,1,4,5,2>的“逆序對”有<3,1>,<3,2>,<4,2>,<5,2>,共4個(如圖所示)。
  請你爲 Sort 公司做一個程序,在儘量短的時間內,統計出“逆序對”的數目。 

【輸入格式】
文件的第一行爲一個整數N(1<=N<=10000)。
文件的第二行爲N個實數。

【輸出格式】
文件共一行,爲“逆序對”的數目。

【輸入輸出樣例】
輸入:
sortt.in
5
3 1 4 5 2
輸入:
sortt.out
4

【分析】
直接枚舉即可。時間複雜度 O(n^2),不會超時。

【代碼】
#include <cstdio>
using namespace std;
double M[10001];
int N;
int T;

int main()
{
    freopen("sortt.in","r",stdin);
    freopen("sortt.out","w",stdout);
    scanf("%d",&N);
    for (int i=1;i<=N;i++)
        scanf("%lf",&M[i]);
    for (int i=1;i<=N-1;i++)
        for (int j=i+1;j<=N;j++)
            if(M[i]>M[j])
                T++;
    printf("%d\n",T);
    return 0;
}

NOIP2000提高組 進制轉換 jzzh 解題報告

描述 Description
我們可以用這樣的方式來表示一個十進制數:將每個阿拉伯數字乘以一個以該數字所處位置的(值減1)爲指數,以10爲底數的冪之和的形式。例如,123可表示爲1*10^2+2*10^1+3*10^0這樣的形式。
與之相似的,對二進制數來說,也可表示成每個二進制數碼乘以一個以該數字所處位置的(值-1)爲指數,以2爲底數的冪之和的形式。一般說來,任何一個正整 數R或一個負整數-R都可以被選來作爲一個數制系統的基數。如果是以R或-R爲基數,則需要用到的數碼爲0,1,....R-1。例如,當R=7時,所需 用到的數碼是0,1,2, 3,4,5和6,這與其是R或-R無關。如果作爲基數的數絕對值超過10,則爲了表示這些數碼,通常使用英文字母來表示那些大於9的數碼。例如對16進制 數來說,用A表示10,用B表示11,用C表示12,用D表示13,用E表示14,用F表示15。在負進制數中是用-R作爲基數,例如-15(+進制)相 當於110001(-2進制),
並且它可以被表示爲2的冪級數的和數:
110001=1*(-2)^5+1*(-2)^4+0*(-2)^3+0*(-2)^2+0*(-2)^1+1*(-2)^0
問題求解:
設計一個程序,讀入一個十進制數的基數和一個負進制數的基數,並將此十進制數轉換爲此負進制下的數:-R∈{-2,-3,-4,....-20}
輸入格式 Input Format
輸入文件有若干行,每行有兩個輸入數據。
第一個是十進制數N(-32768<=N<=32767); 第二個是負進制數的基數-R。
輸出格式 Output Format
輸出此負進制數及其基數,若此基數超過10,則參照16進制的方式處理。【具體請參考樣例】

樣例輸入 Sample Input
30000 -2
-20000 -7
28800 -16
-25000 -16
樣例輸出 Sample Output
30000=11011010101110000(base -2)
-20000=263526(base -7)
28800=19180(base -16)
-25000=7FB8(base -16)

【分析+代碼】
比較基礎的題,只要注意整除函數即可。

以下代碼是BYVoid(www.byvoid.com)大牛的,他的代碼真是精練!
#include <iostream>
#include <cstdio>
using namespace std;
int N,M,base;

inline int Div(int a,int b)
{
    int n;
    n=a/b;
    if (n*b<=a)
        return n;
    return n+1;
}

void work()
{
    int num[100];
    int top=0;
    if(N==0)
    {
        cout<<0;
    }
    int P;
    while (N)
    {
        P=Div(N,base);
        num[++top]=N-P*base;
        N=P;
    }
    for (;top>=1;top--)
    {
        if (num[top]<10)
            cout<<num[top];
        if (num[top]>=10)
            cout<<(char)(num[top]-10+'A');
    }
        cout<<"(base "<<base<<")"<<endl;
}

int main()
{
    freopen("fjz.in","r",stdin);
    freopen("fjz.out","w",stdout);
    while(cin>>N)
    {
        cin>>base;
        M=N;
        cout<<N<<"=";
        work();
    }
    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
恭喜你通过了全部测试点!


NOIP2001 提高組 一元三次方程求解 3cfc 解題報告

問題描述
有形如:ax3+bx2+cx+d=0 這樣的一個一元三次方程。給出該方程中各項的係數(a,b,c,d 均爲實數),並約定該方程存在三個不同實根(根的範圍在-100至100之間),且根與根之差的絕對值>=1。要求由小到大依次在同一行輸出這三個實根(根與根之間留有空格),並精確到小數點後2位。
提示:記方程f(x)=0,若存在2個數x1和x2,且x1<x2,f(x1)*f(x2)<0,則在(x1,x2)之間一定有一個 根。
樣例
輸入:1 -5 -4 20
輸出:-2.00 2.00 5.00

【分析】
由於精度不大,直接枚舉即可。
以下代碼參考了BYVoid(http://www.byvoid.com)的代碼~他的代碼比我的簡練多了~

【代碼】

01 //NOIP2001 一元三次方程求解
02 #include <cstdio>
03 #include <iostream>
04 using namespace std;
05 int main()
06 {
07     double a,b,c,d,x,v;
08     int X;
09     freopen("3cfc.in","r",stdin);
10     freopen("3cfc.out","w",stdout);
11     cin>>a>>b>>c>>d;
12     for (X=-10000;X<=10000;x=(++X)/100.0)
13     {
14         v=a*x*x*x+b*x*x+c*x+d;
15         if (v>=-0.01 && v<=0.01)   
16             printf("%.2lf ",x);   
17     }
18     return 0;
19 }
正在连接评测机...

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

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