当前位置:编程学习 > C/C++ >>

Codeforces Round #131 (Div. 2) 完整题解

第一次进入DIV1,果断易做图,没法下手。赛后先把DIV2解决了吧
A. System of Equations
问a*a+b=m  a+b*b=n,的解a,b,有多少组,因为a,b都非负,而且m和n的范围在1000以内,直接暴力,1000*1000即可
[cpp]
#include<iostream> 
#include<cstring> 
#include<queue> 
#include<cstdio> 
#include<cmath> 
#include<algorithm> 
#define N 55 
#define inf 1<<29 
#define MOD 9973 
#define Max 301  
#define LL long long 
#define eps 1e-7 
#define zero(a) fabs(a)<eps 
#define equal(a,b) zero(a-b) 
using namespace std; 
int main(){ 
    int n,m; 
    while(scanf("%d%d",&n,&m)!=EOF){ 
        int cnt=0; 
        for(int i=0;i<=1000;i++) 
            for(int j=0;j<=1000;j++) 
                if(i*i+j==n&&j*j+i==m) 
                    cnt++; 
        printf("%d\n",cnt); 
    } 
    return 0; 


B. Hometask
由一些数字组成一个整数,能整除2,3,5,而且要最大的。
能同时整除2,5的,末位必然是0,能整除3的,所有位数和必为3的倍数。
首先判断是否有0,如果没有则输出-1.
将所有数字降序排列(因为题目要求最大的整数)
接下来看所有位数和是否为3的倍数,如果是,按顺序输出。
接下来就可能会删除某些数字,删除一位肯定比删除两位要大,而且只可能删除一位或者两位。
如果数字和模3为1,则删除一个尽可能小的,模3为1的数,for(int i=1;i<10;i+=3),如果存在一个这样的数,删除
如果不存在,则接下来可能是删除两位的,而且删除的两位模3都为2,从小往大的找,删除两位
如果数字和模3为2,则删除一个尽可能小的,模3为2的数,for(int i=2;i<10;i+=3),如果存在一个这样的数,删除
如果不存在,则接下来可能是删除两位的,而且删除的两位模3都为1,从小往大的找,删除两位
如果上述情况都不存在,则输出-1
在处理的时候,注意别输出000000就行了,包括删除之后的输出。
代码很shi,就不贴了

C. Game
DIV1的A题,还以为网络流,一直在建图,弱爆了。
可以发现1->2 2->3 3->1为1,其余为2,其实就是循环右移一位是1,两位就是2。
加上一点小贪心,枚举第一台机器,首先将能做的都做了,而且把接下来没有限制的都加入队列
如果这台机器没有任务可做,则到下一台,时间+1,直到所有任务完成。也就是选了一台机子之后,先把能做的全都做了,避免转移花费,而且在做了一个任务之后,要把其它没有限制的加入队列。
[cpp]
#include<iostream> 
#include<cstring> 
#include<queue> 
#include<cstdio> 
#include<cmath> 
#include<algorithm> 
#define N 55 
#define inf 1<<29 
#define MOD 9973 
#define Max 301  
#define LL long long 
#define eps 1e-7 
#define zero(a) fabs(a)<eps 
#define equal(a,b) zero(a-b) 
using namespace std; 
bool mat[205][205]; 
int c[205],n; 
int slove(int s){ 
    int deg[205]; 
    memset(deg,0,sizeof(deg)); 
    queue<int>que[3]; 
    for(int i=1;i<=n;i++){ 
        for(int j=1;j<=n;j++) 
            if(mat[i][j]) 
                deg[i]++; 
        if(deg[i]==0) 
            que[c[i]].push(i); 
    } 
    int ret=0,cnt=n; 
    bool flag[205]; 
    memset(flag,true,sizeof(flag)); 
    while(!que[0].empty()||!que[1].empty()||!que[2].empty()){ 
        if(que[s].empty()) {s=(s+1)%3;ret++;continue;} 
        int u=que[s].front(); 
        que[s].pop(); 
        cnt--; 
        flag[u]=false; 
        for(int i=1;i<=n;i++){ 
            if(mat[i][u]){ 
                deg[i]--; 
                if(deg[i]==0&&flag[i]) 
                    que[c[i]].push(i); 
            } 
        } 
        if(cnt==0) 
            break; 
    } 
    return ret; 

int main(){ 
    while(scanf("%d",&n)!=EOF){ 
        for(int i=1;i<=n;i++){ 
            scanf("%d",&c[i]); 
            c[i]--; 
        } 
        for(int i=1;i<=n;i++){ 
            int k,u; 
            scanf("%d",&k); 
            while(k--){ 
                scanf("%d",&u); 
                mat[i][u]=true; 
            } 
        } 
        int ans=inf; 
        for(int i=0;i<3;i++) 
            ans=min(ans,slove(i)+n); 
        printf("%d\n",ans); 
    } 
    return 0; 


D. Numbers
组合计数。由于不能出现前导0,我们倒序考虑。从9到0,dp[i][j]表示考虑了数字i,长度为j的种数。
然后枚举当前数字取的位数,注意下限,在代码中,表示j位,当前数字i取j-k个 。则之前的取k个,那么就是dp[i+1][k]*c[j][k]  前者是上一轮的种数,后者表示从j个位置 中取出k个放之前的,那么剩下的j-k位放当前数字。
注意数字0的情况要特殊点, 不能有前导0
[cpp]
#include<iostream> 
#include<cstring> 
#include<queue> 
#include<cstdio> 
#include&l

补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,