Codeforces Round #137 (Div. 2)

原创 2013年12月02日 23:59:10

C:

给你n个数和m个数 n , m <= 10^5,每个数 <= 10^7,n个数相乘代表分子,m个数相乘代表分母,现在要把这个分数的最简式也这样子代表出来,也就是说用nout个数代表分子,mout个数代表分母,必须是最简式,每个数的范围都得是 <= 10^7。

思路:

直接统计分子分母的所有素因子的个数,然后消去各个可以消去的素因子即可。

这里我用的筛素数法是O(N)的并且顺便处理出了每个数最小的素因子,这样子的话分解素因子岂不是很简单了。。。复杂度超低nice~

#include 
#include 
#include 
#include 
using namespace std;
#define pb push_back

const int maxp = 10000010;
const int maxn = 100000 + 10;
int pri[777777], pnum, minp[maxp];
bool vis[maxp];
int a[maxn], b[maxn], cnt1[maxp], cnt2[maxp];

// O(n)筛素数法,minp[i]表示i的最小的素因子
void get_prime(int n) {
    vis[1] = 1; pnum = 0;
    for(int i = 2;i <= n; i++) {
        if(!vis[i]) {
            pri[pnum++] = i;
            minp[i] = i;
        }
        for(int j = 0;j < pnum; j++) {
            if(pri[j] * i > n)  break;
            vis[pri[j] * i] = 1;
            minp[pri[j] * i] = pri[j];
            if(i % pri[j] == 0) break;
        }
    }
}

vector pr1, pr2;
int main() {
    get_prime(10000000);

    int n, m, mx = 0;
    scanf("%d%d", &n, &m);
    for(int i = 0; i < n; i++) {
        scanf("%d", &a[i]);
        mx = max(mx, a[i]);
        int cur = a[i];
        while(cur > 1) {
            cnt1[minp[cur]] ++;
            cur /= minp[cur];
        }
    }
    for(int i = 0;i < m; i++) {
        scanf("%d", &b[i]);
        mx = max(mx, b[i]);
        int cur = b[i];
        while(cur > 1) {
            cnt2[minp[cur]] ++;
            cur /= minp[cur];
        }
    }
    for(int i = 1;i <= mx; i++)
        cnt1[i] = cnt2[i] = min(cnt1[i], cnt2[i]);
    for(int i = 0;i < n; i++) {
        int cur = a[i], now = cur;
        while(cur > 1) {
            int tmp = minp[cur];
            if(cnt1[tmp]) now /= tmp, cnt1[tmp]--;
            cur /= tmp;
        }
        pr1.pb(now);
    }
    for(int i = 0;i < m; i++) {
        int cur = b[i], now = cur;
        while(cur > 1) {
            int tmp = minp[cur];
            if(cnt2[tmp])   now /= tmp, cnt2[tmp]--;
            cur /= tmp;
        }
        pr2.pb(now);
    }
    sort(pr1.begin(), pr1.end());
    sort(pr2.begin(), pr2.end());
    printf("%d %d\n", n, m);
    for(int i = 0;i < n; i++)   printf("%d ", pr1[i]); puts("");
    for(int i = 0;i < m; i++)   printf("%d ", pr2[i]); puts("");
    return 0;
}


D:

直接贪心从a数列中从大到小到从小到大的b数列中选择尽可能多的和 >= x的即可,最好的排名肯定是1的。

E:

要你用m个字母组成n个字母,问有多少种情况,这里有些限制有些字母不能组合。

思路:很裸的矩阵二分幂

#include 
#include 
#include 
using namespace std;
typedef __int64 ll;

const int mod = 1000000007 ;

char s[11];

int pow_mod(int q[55][55], ll n, int m) {
    int a[55][55], aa[55][55], qq[55][55];
    for(int i = 0;i < m; i++)
        for(int j = 0;j < m; j++)
            a[i][j] = i == j ? 1 : 0;
    while(n) {
        if(n & 1) {
            for(int i = 0;i < m; i++)
                for(int j = 0;j < m; j++) {
                    aa[i][j] = 0;
                    for(int k = 0;k < m; k++)
                        aa[i][j] = (aa[i][j] + (ll)a[i][k]*q[k][j])%mod;
                }
            for(int i = 0;i < m; i++)
                for(int j = 0;j < m; j++)
                    a[i][j] = aa[i][j];
        }
        for(int i = 0;i < m; i++)
            for(int j = 0;j < m; j++) {
                qq[i][j] = 0;
                for(int k = 0;k < m; k++)
                    qq[i][j] = (qq[i][j] + (ll)q[i][k]*q[k][j])%mod;
            }
        for(int i = 0;i < m; i++)
            for(int j = 0;j < m; j++)
                q[i][j] = qq[i][j];
        n /= 2;
    }
    ll ret = 0;
    for(int i = 0;i < m; i++)
        for(int j = 0;j < m; j++)
            ret += a[i][j];
    return ret%mod;
}

int a[55][55];
int main() {
    int  m, k;
    ll n;
    scanf("%I64d%d%d", &n, &m, &k);
    for(int i = 0;i < m; i++)  
        for(int j = 0;j < m; j++)
            a[i][j] = 1;
    for(int i = 0;i < k; i++) {
        scanf("%s", s);
        int x, y;
        if(s[0] <= 'Z')
            x = 26 + s[0] - 'A';
        else
            x = s[0] - 'a';
        if(s[1] <= 'Z')
            y = 26 + s[1] - 'A';
        else
            y = s[1] - 'a';
        a[x][y] = 0;
    }
    printf("%d\n", pow_mod(a, n-1, m));
    return 0;
}

相关文章推荐

【优化&大师级代码欣赏】Codeforces Round #137 (Div. 2) / 222B Cosmic Tables (矩阵)

B. Cosmic Tables http://codeforces.com/problemset/problem/222/B time limit per test 3 seconds m...

Codeforces Round #137 (Div. 2), problem: (C)

大神代码直接看瞎了,收获好大。。。 C. Reducing Fractions time limit per test 2 seconds memo...

Codeforces Beta Round #98 (Div. 2) / 137A Postcards and photos (模拟)

A. Postcards and photos http://codeforces.com/problemset/problem/137/A time limit per test 2 seco...

Codeforces Round #137 (Div. 2)

哎、、 好水啊 准备敲之前一定要想好思路、、、到快结束的时候思路才对、、而且有个JR还总cha我、、最后依然一题悲剧、、 A. Shooshuns and Sequence 题意:大水、就是把...

【Codeforces Round 263 (Div 2)A】【水题 认真读题】Appleman and Easy Task 每个点的相邻o是否都为偶数

Appleman and Easy Task time limit per test 1 second memory limit per test 256 megabytes ...

Codeforces Round #350 (Div. 2) F. Restore a Number(有一位数为n的数,在后面添上n这个数,然后将所有的数字打乱输出,再给你一串原数字的子串,输出最小)

F. Restore a Number time limit per test 2 seconds memory limit per test 256 megabytes ...

Codeforces Round #365 (Div. 2) A(暴力) B(数学技巧) C(二分)D(线段树+离散)E(乘除法DP+约数分解+map映射)

传送门:A. Mishka and Game 暴力记录两人赢的次数,最后将次数再比较一次即可 #include using namespace std; int n; int main()...

【Codeforces Round 271 (Div 2)F】【贪心 线段树】Ant colony 区间段内是其他所有数因子的数的个数

Ant colony time limit per test 1 second memory limit per test 256 megabytes input ...

【Codeforces Round 328 (Div 2)A】【水题】PawnChess 棋子向上向下走

#include #include #include #include #include #include #include #include #include #include #include #...

【Codeforces Round 335 (Div 2) C】【贪心 脑洞 有趣排序】Sorting Railway Cars 全排列排序可以提前后提后的最小操作数

C. Sorting Railway Cars time limit per test 2 seconds memory limit per test 256 megabytes inpu...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Codeforces Round #137 (Div. 2)
举报原因:
原因补充:

(最多只允许输入30个字)