Codeforces Round #315 (Div. 2) (ABCD题)

A. Music

题意:

一首歌长度为S秒,已经下载了T秒,下载速度为每q秒的现实时间能下载下来(q-1)秒 的歌曲。现在开始听歌,如果听到还没下载的地方就从0秒的地方开始replay,求一首歌听完需要从0秒听几次(包括一开始那次)

思路:

我们可以用路程-时间的思路来考虑这道题。
假设两位选手“播放”与“下载”,“播放”的起点是0m处,“下载”的起点是Tm处,终点在Sm处,“播放”的速度是1m/s,“下载”的速度是(q-1)/q m/s。
假设两名选手在Xm处相遇,那么:
(X-T) / ((q-1)/q)= (X-0)/1
转化下就可得到X = qT。
那么第qT秒就是第一次需要replay的地方。replay以后,T = X,继续计算qT,直到qT > S,累计replay的次数即可。

代码:

/*
* @author FreeWifi_novicer
* language : C++/C
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

using namespace std;

#define clr( x , y ) memset(x,y,sizeof(x))
#define cls( x ) memset(x,0,sizeof(x))
#define mp make_pair
#define pb push_back
typedef long long lint;
typedef long long ll;
typedef long long LL;

int main(){
//  freopen("input.txt","r",stdin);
    int t,s,q;
    while(cin >> t >> s >> q){
        int ans = 1;
        int x = s*q;
        while(x < t){
            ans++;
            x = x*q;
        }
        cout << ans << endl;
    }
    return 0;
}

B - Inventory

题意:

把n个数组成的数列变成由1~n组成的数列,1~n每个数只能且必须出现一次。

思路:

map累计每个元素出现次数,再从头扫一遍,出现次数大于1的元素更换为出现次数为0的元素,更新map。
统计下,缺谁补谁呗

代码:

/*
* @author FreeWifi_novicer
* language : C++/C
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

using namespace std;

#define clr( x , y ) memset(x,y,sizeof(x))
#define cls( x ) memset(x,0,sizeof(x))
#define pb push_back
typedef long long lint;
typedef long long ll;
typedef long long LL;
map<int,int>mp;
vector<int>q;
int a[100005];
int main(){
//  freopen("input.txt","r",stdin);
    int n;
    while(cin >> n){
        mp.clear();
        q.clear();
        cls(a);
        for(int i = 1 ; i <= n ; i++){
            int tmp;
            scanf("%d",&tmp);
            mp[tmp]++;
            a[i] = tmp;
        }
        for(int i = 1 ; i <= n ; i++){
            if(mp[i] < 1) {
                q.pb(i);
            }
        }
        int k = 0;
        for(int i = 1 ; i <= n ; i++){
            if(mp[a[i]] >= 2 || a[i] > n){
                mp[a[i]]--;
                a[i] = q[k++];
            }
        }
        for(int i = 1 ; i < n ; i++){
            printf("%d ",a[i]);
        }
        printf("%d\n",a[n]);
    }
    return 0;
}

C - Primes or Palindromes?

题意:

定义π(n) = 不大于n的素数个数,
定义rub(n) = 不大于n的回文数个数,
输入p,q(1/42 <= p/q <= 42),求满足π(n) <= p/q * rub(n)的n的最大值。

思路:

你只需要知道,π(n) 的增长速度大于rub(n),打个表看看什么时候π(n) > 42* rub(n),发现大概是n = 2*10^6的时候,再加上3s的时限与cf超越各大oj的机器性能。
枚举大法好。

代码:

/*
* @author FreeWifi_novicer
* language : C++/C
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

using namespace std;

#define clr( x , y ) memset(x,y,sizeof(x))
#define cls( x ) memset(x,0,sizeof(x))
#define mp make_pair
#define pb push_back
typedef long long lint;
typedef long long ll;
typedef long long LL;
const int maxn = 10000000+5;
bool notPrime[maxn+5];

void Prime(void){
    memset(notPrime,false,sizeof(notPrime));
    for(int i = 2; i*i <= maxn; i++){
        if(!notPrime[i]){
            for(int j = i*i; j <= maxn; j += i){
                notPrime[j] = true;
            }
        }
    }
}
int reverse(int n)  {  
    int res = 0;  
    while(n){  
        int d = n % 10;  
        res = res*10 + d;  
        n /= 10;  
    }  
    return res;  
}  
bool hui(int n){
    if(reverse(n) == n) return true;
    return false;
}
vector<int>v;
int main(){
  //freopen("output.txt","w+",stdout);
    int p,q;
    cin >> p >> q;
    Prime();
    lint pr = 0,hu=0;
    v.clear();
    v.pb(1);
    for(int i = 1 ; i <= 10000000; i++){
        if(!notPrime[i] && i!= 1){
            pr++;
        }
        if(hui(i)){
            hu++;
        }
        if(pr * q <= hu*p){
            v.pb(i);
        }
    }
    if(v.size() >= 1){
        cout <1] <return 0;
    }
    cout << "Palindromic tree is better than splay tree" << endl;
    return 0;
}

D - Symmetric and Transitive

题意:

求1到n的n个元素组成的二元关系集合中,满足对称性和传递性但不满足自反性的二元组关系集合的个数。

思路:

赛后看到这个题(手速过慢比赛的时候没来得及看),觉得自己的离散数学知识都喂队友了。。

Bell number,又名贝尔数,表示基数为n的集合划分数目,也表示n元素集合的等价关系的数目,于是我们可以发现ans[n] = Bell[n+1] - Bell[n],从下一个等价关系个数中减去从当前等价关系个数,即为当前不满足自反的二元组关系个数。
贝尔数的推导可以用贝尔三角形或第二类斯特林数和。
这个题重在题意理解和样例理解上:
样例1:ρ = ∅
样例2:ρ = ∅ , ρ = {(x, x)} , ρ = {(y, y)}.
样例3:
0个元素(空集):
ρ = ∅;
1个元素:
ρ= {(x, x)},ρ= {(y, y)},ρ= {(z, z)};
2个元素:
ρ= {(x, x), (y, y)},ρ= {(x, x), (z, z)},ρ= {(y, y), (z, z)};
3个元素:
无;
4个元素:
ρ= {(x, x), (y, y), (x, y), (y, x)},ρ= {(y, y), (z, z), (y, z), (c, y)},ρ= {(x, x), (z, z), (x, z), (z, x)}
5、6个元素:无
一共10个。

/*
* @author FreeWifi_novicer
* language : C++/C
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

using namespace std;

#define clr( x , y ) memset(x,y,sizeof(x))
#define cls( x ) memset(x,0,sizeof(x))
#define mp make_pair
#define pb push_back
typedef long long lint;
typedef long long ll;
typedef long long LL;

const int mod = 1e9+7;
const int maxn = 4000 + 5;
lint B[maxn][maxn];
//注释语句可以打印bell三角形
void init(){
    B[1][1] = 1;
    //cout << 1 <
    for(int i = 2 ; i <= 4001; i++){
        B[i][1] = B[i-1][i-1];
        //cout << B[i][1] << ' ';
        for(int j = 2 ; j <= i ; j++){
            B[i][j] = (B[i-1][j-1] + B[i][j-1]) % mod;
            //cout << B[i][j] <<' ';
        }
    }
}
int main(){
    init();
    int n;
    while(cin >> n)
        cout << B[n+1][n] % mod << endl;
    return 0;
}

你可能感兴趣的:(ACM,and,novicer,大大小小的比赛,数学-数论,枚举)