1. 程式人生 > >記2018/4/29 qbxt 測試

記2018/4/29 qbxt 測試

def div2 三角形 std 不同 Go include num isp

    記 2018/4/29 qbxt 測試(提高基礎班)

      簡單的 NOIP 模擬賽
  競賽時間: 2018 4 29 13:30-17:00

題目名稱 乘法 求和 計數
輸入文件名 mul.in sum.in count.in
輸出文件名 mul.out sum.out count.in
每個測試點時限 1 sec 4 sec 1 sec
內存限制
128MB
128MB 128MB
測試點數目 10 10 10
每個測試點分值 10 10 10
是否有部分分
題目類型 傳統 傳統 傳統

T1 期望得分:100;實際得分:100

          乘法

【問題描述】

  給定正整數n,m,p,你需要輸出 n * m 對 p 取模後的值
【輸入文件】

  輸入文件為 mul.in

  輸入為一行 n, m, p

【輸出文件】

  輸出文件為 mul.out

  輸出一行為一個整數,為所求的答案

【輸入輸出樣例】

mul.in mul.out
11 22 10 2

【數據規模和約定】

  對於30%的數據,n, m, p <=10000;

  對於60%的數據,n, m, p <= 109

  對於100%的數據, n, m, p <= 1018

【一些提示】

    以下是一些對取模操作的介紹:
  一個整數a對一個整數p取模的值,是一個不超過p的非負整數b,並且a-b是p的倍數。可以證明,滿足條件的b有且只有一個;


  一些運算在取模前後仍然成立,例如:

    兩個數的和對p取模的值等於兩個數先對p取模,再求和,在取模;

    兩個數的乘積對p取模的值等於兩個數先對p取模,再求乘積,再取模

    但兩個數的除法沒有類似的性質

思路:快速乘(類似於快速冪) or 高精

技術分享圖片
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
long long n, m, p;
long long Mul(long long x, long long y){
    long long
res = 0; x %= p; y %= p; while(y) { if(y & 1) res = (res+x) % p; x = (x+x) % p; y >>= 1; } return res; } int main() { //freopen("mul.in","r",stdin); //freopen("mul.out","w",stdout); cin >> n >> m >> p; cout<< Mul(n, m); //fclose(stdin); fclose(stdout); return 0; }
快速乘 技術分享圖片
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
namespace BigInteger
{
    #define maxn 10005
    using std::sprintf;
    using std::string;
    using std::max;
    using std::istream;
    using std::ostream;

    struct Big_integer
    {
        int d[maxn],len;
        void clean()
        {
            while(len>1&&!d[len-1])
                len--;
        }
        Big_integer()
        {
            memset(d,0,sizeof(d));
            len=1;
        }
        Big_integer(int num)
        {
            *this=num;
        }
        Big_integer(char* num)
        {
            *this=num;
        }
        Big_integer operator = (const char* num)
        {
            memset(d,0,sizeof(d));
            len=strlen(num);
            for(int i=0;i<len;i++)
              d[i]=num[len-1-i]-0;
            clean();
            return *this;
        }
        Big_integer operator = (int num)
        {
            char s[10005];
            sprintf(s,"%d",num);
            *this=s;
            return *this;
        }
        Big_integer operator + (const Big_integer& b)
        {
            Big_integer c=*this;
            int i;
            for(i=0;i<b.len;i++)
            {
                c.d[i]+=b.d[i];
                if(c.d[i]>9)
                {
                    c.d[i]%=10;
                    c.d[i+1]++;
                }
            }
            while(c.d[i]>9)
            {
                c.d[i++]%=10;
                c.d[i]++;
            }
            c.len=max(len,b.len);
            if(c.d[i]&&c.len<=i)
              c.len=i+1;
            return c;
        }
        Big_integer operator - (const Big_integer& b)
        {
            Big_integer c=*this;
            int i;
            for(i=0;i<b.len;i++)
            {
                c.d[i]-=b.d[i];
                if(c.d[i]<0)
                {
                    c.d[i]+=10;
                    c.d[i+1]--;
                }
            }
            while(c.d[i]<0)
            {
                c.d[i++]+=10;
                c.d[i]--;
            }
            c.clean();
            return c;
        }
        Big_integer operator * (const Big_integer& b) const
        {
            int i,j;
            Big_integer c;
            c.len=len+b.len;
            for(j=0;j<b.len;j++)
              for(i=0;i<len;i++)
                c.d[i+j]+=d[i]*b.d[j];
            for(i=0;i<c.len-1;i++)
            {
                c.d[i+1]+=c.d[i]/10;
                c.d[i]%=10;
            }
            c.clean();
            return c;
        }
        Big_integer operator % (const Big_integer& b)
        {
            int i,j;
            Big_integer a=0;
            for(i=len-1;i>=0;i--)
            {
                a=a*10+d[i];
                for(j=0;j<10;j++)
                  if(a<b*(j+1))
                    break;
                  a=a-b*j;
            }
            return a;
        }
        bool operator < (const Big_integer& b) const
        {
            if(len != b.len) return len<b.len;
            for(int i=len-1;i>=0;i--)
              if(d[i]!=b.d[i])
                return d[i]<b.d[i];
            return false;
        }
        string str()const
        {
            char s[maxn]={};
            for(int i=0;i<len;i++)
              s[len-1-i]=d[i]+0;
            return s;
        }
    };
    istream& operator >> (istream& in,Big_integer& x)
    {
        string s;
        in>>s;
        x=s.c_str();
        return in;
    }

    ostream& operator << (ostream& out,const Big_integer& x)
    {
        out<<x.str();
        return out;
    }
}
using namespace BigInteger;
using namespace std;
Big_integer a,b,k;
int main()
{
    //freopen("mul.in","r",stdin);
    //freopen("mul.out","w",stdout);
    cin>>a>>b>>k;
    cout<<a*b%k;
    //fclose(stdin);
    //fclose(stdout);
    return 0;
}
高精

T2 期望得分:30;實際得分:0 qwq

      求和

【題目描述】

  給定n個正整數d1 , d2 , d3 ..... dn如果取出其中的任意兩個數(可以相同) ,則可以得到這兩個數的和。對於n個數,則至多可以產生n*(n + 1) / 2 種不同的和。
  給出正整數 m,你需要判斷: 是否存在兩個整數 u, v , 滿足 du + dv = m.
【輸入文件】
  輸入文件為 sum. in
  本題一個輸入中包含多組數據。 輸入第一行為一個整數 T , 表示數據組數。對於每組數據, 輸入的第一行為兩個正整數 n, m,輸入的第二行為 n 個正整數 d1, d2, d3 ..... dn
【輸出文件】
  輸入文件為 sum.out
  輸出 T 行, 每行一個整數。 如果正整數 u, v 存在, 則輸出 1; 否則輸出 0
【輸入輸出樣例】

sum.in sum.out

2

3 3

2 3 4

3 4

1 2 4

0

1






  

【數據規模和約定】
  對於30%的數據,滿足 n <= 1000, m <= 10000;

  對於60%的數據,滿足 n <= 105

  對於另30%的數據,滿足 m <= 107;

  對於100%的數據,滿足 1 <= n <= 106, 1 <= di <= 109, 1 <= T <= 20.

【一些提示】
在下發文件中附有文件 sample.cpp, 包含了自定義函數 read()及其使用示例。 對於本題,請務必使用 read()函數進行讀入, 否則可能會有時間的問題。
思路: 30 分: 暴力
    60 分: 排序後, 兩根指針進行掃?。
    另 30 分: 用計數數組記錄數的分布
    100 分: 在使用計數數組的基礎上進行拓展。考慮設置一個數 b ,把每個di 寫成 di = ai * b + ri ;並且把每個 di 按 ai 的值分成若幹組,ai 相同的數放在一組裏。
    考慮一次性處理某一組的數。 如果假設 du + dv = m 的一個數在某一組中,那麽另一個數的分布範圍一定不超過兩組。 所以, 如果要檢測某一組的數是否可以作為一個加數, 只需要把另外的兩組放入計數數組即可。 這樣就解決了計數數組開不下的問題。

技術分享圖片
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
typedef long long ll;
typedef vector<int>::iterator iter;
const int N = 1000010, M = 100000;
int d[N];
int a[M];
vector<int> block[M];
int cnt[M * 4];
int read()
{
    int x=0;char ch=getchar();
    while(ch<0||ch>9) ch=getchar();
    while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
    return x;
}
int main()
{
    freopen("sum.in","r",stdin);
    freopen("sum.out","w",stdout);
    setvbuf(stdin, new char[1 << 20], _IOFBF, 1 << 20);
    setvbuf(stdout, new char[1 << 20], _IOFBF, 1 << 20);
    int T = read();
    while (T--)
    {
        
        int n = read(), m = read();
        int maxblock = m / M;
        int ans = 0;
        for (int i = 0; i <= maxblock; i++)
            block[i].clear();
        int tmptme = clock();
        while (n--)
        {
            int x = read();
            int y = x % M;
            x /= M;
            block[x].push_back(y);
        }
        for (int i = 0; i <= maxblock; i++)
        {
            int lblock = (m - (i + 1) * M + 1) / M;
            int rblock = (m - i * M) / M;
            int base = lblock * M;
            for (int j = lblock; j <= rblock; j++)
            {
                for (iter it = block[j].begin(); it != block[j].end(); it++)
                {
                    cnt[*it + j * M - base] = 1;
                }
            }
            for (iter it = block[i].begin(); it != block[i].end(); it++)
            {
                if (cnt[m - i * M - *it - base])
                {
                    ans = 1;
                    break;
                }
            }
            for (int j = lblock; j <= rblock; j++)
            {
                for (iter it = block[j].begin(); it != block[j].end(); it++)
                {
                    cnt[*it + j * M - base] = 0;
                }
            }
            if (ans) break;
        }
        cout << ans << endl;
    }
    return 0;            
}
標程

T3 期望得分:40;實際得分:40;

      計數
【問題描述】
  楊輝三角是一個滿足如下條件的三角形矩陣:
  邊界條件:f [ i ] [ 0 ] = f [ i ] [ i ] = 1 , i >= 0 .
  其余部分:f [ i ] [ j ] = f [ i - 1 ] [ j - 1 ] + f [ i - 1 ] [ j ] , 如果( i, j )不在邊界上
  由此可以得出楊輝三角的前5行大致如下:
    1
    1 1
    1 2 1
    1 3 3 1
    1 4 6 4 1
  現在,給定正整數n你需要計算楊輝三角前n行有多少個偶數
【輸入文件】
  輸入文件為 技術分享圖片count.in。
  輸入文件為一行一個正整數n。
【輸出文件】
  輸入文件為 cs.out。
  輸出一行一個整數, 為楊輝三角前n行的偶數個數。
【輸入輸出樣例】
  5 4
【數據規模和約定】
  對於40%的數據,滿足n<=1000。
  對於70%的數據,滿足n<=106
  對於90%的數據,滿足n<=109
  對於100%的數據,滿足n<=10100

思路:楊輝三角的奇偶分布是一個經典的分形圖形。 由此可以觀察出的規律有:楊輝三角的前 2n 行的奇數個數是 3n 個,如果找到一個 k,使 2k <= n < 2k-1, 那麽前 2k 行的奇數個數可以單獨計算; 而余下部分兩邊對稱, 所以可以遞歸算其中的一邊, 再乘以 2 加入答案。
上述算法計算出的是楊輝三角前 n 行有多少個奇數, 作差即可得到偶數的個數。
對於最後一個測試點, 需要使用高精度來支持上述做法。

技術分享圖片
#include<algorithm>
#include<cstdio>
using namespace std;
int n, sum;
int a[1000][1000];

int main() {
    //freopen("count.in","r",stdin);
    //freopen("count.out","w",stdout);
    scanf("%d", &n);
    a[0][0] = 1;
    for(int i = 0; i < n; i++)
        for(int j = 0; j < i+1; j++) {
            if(i == 0) a[i][j] = 1;
            else a[i][j] = a[i-1][j-1]+a[i-1][j];
            if(a[i][j]%2 == 0) sum++;
        }
    printf("%d", sum);
    //fclose(stdin); fclose(stdout);
    return 0;
}
40分暴力 技術分享圖片
#include<iostream>
using namespace std;
long long n;
long long work(long long n)
{
    if(n==0 || n==1 )return 0;
    if(n&1)return 2*work(n/2)+work(n/2+1)+(n/2)*(n/2+1)/2;
    else return 3*work(n/2)+(n/2)*(n/2-1)/2; 
}
int main()
{
    //freopen("count.in","r",stdin);
    //freopen("count.out","w",stdout);
    cin>>n;
    cout<<work(n); 
    //fclose(stdin);fclose(stdout);
    return 0;
}
90分遞歸 沒有高精 技術分享圖片
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<string>
using namespace std;
const int N = 201;


struct bignum
{
    int a[N];
    int n;
    bignum()
        {
            n = 0;
            memset(a, 0, sizeof(a));
        }
    bignum(string s)
        {
            memset(a, 0, sizeof(a));
            n = s.size();
            for (int i = 0; i < n; i++)
                a[i] = s[n - 1 - i] -0;
        }
    bignum(int x)
        {
            memset(a, 0, sizeof(a));
            n = 0;
            while (x)
            {
                a[n] = x % 10;
                x /= 10;
                n++;
            }
        }
    void deal()
        {
            for (int i = 0; i < n; i++)
            {
                if (a[i] < 0)
                {
                    int tmp = (-a[i] - 1) / 10 + 1;
                    a[i] += 10 * tmp;
                    a[i + 1] -= tmp;
                }
                if (a[i] >= 10)
                {
                    int tmp = a[i] / 10;
                    a[i] -= 10 * tmp;
                    a[i + 1] += tmp;
                    if (i == n - 1 && a[i + 1] > 0) n++;
                }
            }
            while (n > 0 && a[n - 1] == 0) n--;
        }
    void div2()
        {
            int tmp = 0;
            for (int i = n - 1; i >= 0; i--)
            {
                int tmp_ = a[i] & 1;
                a[i] = (a[i] + tmp * 10) >> 1;
                tmp = tmp_;
            }
            deal();
        }
    void print()
        {
            for (int i = n - 1; i >= 0; i--)
                cout << a[i];
            cout << endl;
        }
};



bignum operator + (const bignum &a, const bignum &b)
{
    bignum c;
    c.n = max(a.n, b.n);
    for (int i = 0; i < c.n; i++)
        c.a[i] = a.a[i] + b.a[i];
    c.deal();
    return c;
}


bignum operator - (const bignum &a, const bignum &b)
{
    bignum c;
    c.n = max(a.n, b.n);
    for (int i = 0; i < c.n; i++)
        c.a[i] = a.a[i] - b.a[i];
    c.deal();
    return c;
}

bignum operator * (const bignum &a, const bignum &b)
{
    bignum c;
    c.n = a.n + b.n - 1;
    for (int i = 0; i < a.n; i++)
        for (int j = 0; j < b.n; j++)
            c.a[i + j] += a.a[i] * b.a[j];
    c.deal();
    return c;
}
bool no_bigger_than(const bignum &a, const bignum &b)
{
    if (a.n < b.n) return 1;
    if (b.n < a.n) return 0;
    
    for (int i = a.n - 1; i >= 0; i--)
    {
        if (a.a[i] > b.a[i]) return 0;
        if (a.a[i] < b.a[i]) return 1;
    }
    return 1;
}

bignum calc(bignum n)
{
    if (n.n == 0) return 0;
    bignum ret(1);
    bignum now(1);
    bignum big2(2);
    bignum big3(3);
    while (no_bigger_than(now * big2, n))
    {
        now = now * big2;
        ret = ret * big3;
        
    }
    /*
    cout << "*****" << endl;
    n.print();
    now.print();
    ret.print();
    cout << "*****" << endl;
    */
    return ret + big2 * calc(n - now);
}


int main()
{
    freopen("count.in","r",stdin);
    freopen("count.out","w",stdout);
    string s;
    cin >> s;
    bignum a(s);
    bignum n(s);
    bignum b(1);
    //b.print();
    bignum c = a + b;
    //a.print();
    //c.print();
    //return 0;
    a = a * c;
    //a.print();
    a.div2();
    //a.print();
    (a - calc(n)).print();
    return 0;
}
標程


附加題:HDU 矩形面積並


記2018/4/29 qbxt 測試