codeforces选做

收录了最近本人完成的一部分codeforces习题,不定期更新

codeforces 1132E Knapsack

注意到如果只使用某一种物品,那么这八种物品可以达到的最小相同重量为\(840\)

故答案一定可以被写成\(840k+x(k,x\in N_+)\),我们将\(x\)称为”余下的部分”

故而设\(dp[i][j]\)为当前考虑了前\(i\)个物品,它们所占的余下的部分的重量为\(j\)时,最多可以组成多少个\(840\)

对于每个\(i\)预处理出枚举上界暴力转移即可

#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define lowbit(x) (x)&(-x)
#define rep(i,a,b) for (int i=a;i<=b;i++)
#define per(i,a,b) for (int i=a;i>=b;i--)
#define maxd 1000000007
typedef long long ll;
const int N=100000;
const double pi=acos(-1.0);
ll w,a[10],ans=0,dp[9][100100];

ll read()
{
    ll x=0,f=1;char ch=getchar();
    while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    return x*f;
}

int main()
{
    w=read();
    rep(i,1,8) a[i]=read();
    ll maxp=8*840;
    memset(dp,-1,sizeof(dp));
    dp[0][0]=0;
    rep(i,1,8)
    {
        rep(j,0,maxp)//余下的重量
        {
            if (dp[i-1][j]==-1) continue;
            ll k=min(1ll*840/i,a[i]);
            rep(p,0,k)//当前有多少作为余下的部分
            {
                dp[i][j+p*i]=max(dp[i][j+p*i],dp[i-1][j]+(a[i]-p)/(840/i));
            }
        }
    }
    ll ans=0;
    rep(i,0,min(w,maxp))
    {
        if (dp[8][i]==-1) continue;
        ans=max(ans,i+min((w-i)/840,dp[8][i])*840);
    }
    printf("%lld",ans);
    return 0;
} 

codeforces1154G Minimum Possible LCM

根据\(lcm(x,y)=\frac{xy}{gcd(x,y)}\)进行计算

枚举约数\(d\),每次找到满足\(d|x\)的最小的两个\(x\),用它们更新答案即可

为什么这样做可行?我们假设满足\(d|x?\)的数从小到大一次为\(a_1,a_2,\cdots,a_k?\)

不妨对\(a_1,a_2,a_k(k>2)\)这三个数进行分析,并且我们保证\(gcd(a_1,a_k)=d\),否则我们可以在枚举更大的\(d\)的时候考虑到这一组

  • 若\(gcd(a_1,a_2)=d\),那么一定有\(\frac{a_1a_2}{gcd(a_1,a_2)}<\frac{a_1a_k}{gcd(a_1,a_k)}\)
  • 若\(gcd(a_1,a_2)>d?\),则\(\frac{a_1a_2}{gcd(a_1,a_2)}<\frac{a_1a_2}{d}<\frac{a_1a_k}{d}?\)

证毕

#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define lowbit(x) (x)&(-x)
#define rep(i,a,b) for (int i=a;i<=b;i++)
#define per(i,a,b) for (int i=a;i>=b;i--)
typedef long long ll;
const int N=100000;
const double pi=acos(-1.0);
int n,a[1001000],cnt[10010000];
vector<int> ans;

int read()
{
    int x=0,f=1;char ch=getchar();
    while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    return x*f;
}

ll gcd(ll x,ll y)
{
    if (!y) return x;else return gcd(y,x%y);
}

int main()
{
    n=read();ll maxd=0;
    rep(i,1,n) {a[i]=read();cnt[a[i]]++;maxd=max(maxd,1ll*a[i]);}
    ll lcm=(ll)1e18+7,val1,val2;
    rep(i,1,maxd)
    {
        int j;ans.clear();
        for (j=i;j<=maxd;j+=i)
        {
            if (!cnt[j]) continue;
            int tmp=cnt[j];
            while ((tmp) && (ans.size()<2))
            {
                ans.push_back(j);
                tmp--;
            }
            if (ans.size()==2) break;
        }
        if (ans.size()!=2) continue;
        ll now=1ll*ans[0]*ans[1]/gcd(ans[0],ans[1]);
        if (now<lcm)
        {
            lcm=now;val1=ans[0];val2=ans[1];
        }
    }
    ll pos1=0,pos2=0;
    rep(i,1,n)
    {
        if ((!pos1) && (a[i]==val1)) pos1=i;
        else if ((!pos2) && (a[i]==val2)) pos2=i;
    }
    if (pos1>pos2) swap(pos1,pos2);
    printf("%lld %lld",pos1,pos2);
    return 0;
}

codeforces 1120D Power Tree

如果不要输出方案的话那就可以大力\(dp\),记\(dp[u][0/1]\)为控制以\(u\)为根的子树的最小代价,其中\(0\)表示不选\(u\)的祖先\(1\)表示选,考虑\(u\)的儿子是不需要选祖先或者某一个需要祖先来进行转移

然而似乎输出方案很难写。。。弃了弃了看题解

将控制一个点的操作转化到树的dfs序上,也就是控制了一段区间,注意到这个\(dfs\)序我们只需要保留叶子结点

为了转化区间操作,我们将这个\(dfs\)转化成差分序列,即一次对\([l,r]\)的操作可以看做是在\(l\)加上一个数同时在\(r+1\)上减去一个数

考虑题目是要求最后能使得整个序列都变成\(0\),等价于让这个差分序列变成\(0\)

也就是说对于每个点我们都希望有一条能单独修改它的路径

将差分序列的每个位置看成是一个点,一次修改看成是一条边,跑kruskal即可

#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define lowbit(x) (x)&(-x)
#define rep(i,a,b) for (int i=a;i<=b;i++)
#define per(i,a,b) for (int i=a;i>=b;i--)
#define maxd 1000000007
typedef long long ll;
const int N=100000;
const double pi=acos(-1.0);
struct sqnode{
    int to,nxt;
}sq[400400];

struct edgenode{
    int u,v,w,id;
}edge[200200];
bool operator <(const edgenode &p,const edgenode &q)
{
    return p.w<q.w;
}
int n,w[200200],all=0,head[200200],l[200200],r[200200],tot=0,tim=0,fa[200200];
bool vis[200200];

int read()
{
    int x=0,f=1;char ch=getchar();
    while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    return x*f;
}

int find(int x)
{
    if (fa[x]==x) return x;
    fa[x]=find(fa[x]);
    return fa[x];
}

void dfs(int u,int fu)
{
    int i;
    l[u]=maxd;r[u]=0;
    for (i=head[u];i;i=sq[i].nxt)
    {
        int v=sq[i].to;
        if (v==fu) continue;
        dfs(v,u);vis[u]=1;
        l[u]=min(l[u],l[v]);
        r[u]=max(r[u],r[v]);
    }
    if ((!vis[u]) && (u!=1)) {l[u]=(++tim);r[u]=tim;}
    edge[++tot]=(edgenode){l[u],r[u]+1,w[u],u};
}

void add(int u,int v)
{
    all++;sq[all].to=v;sq[all].nxt=head[u];head[u]=all;
}

int main()
{
    n=read();
    rep(i,1,n) w[i]=read();
    rep(i,1,n-1)
    {
        int u=read(),v=read();
        add(u,v);add(v,u);
    }
    memset(vis,0,sizeof(vis));
    dfs(1,0);
    sort(edge+1,edge+1+n);
    ll ans=0;
    rep(i,1,tim+1) fa[i]=i;
    memset(vis,0,sizeof(vis));
    int l=1,r=1;
    for (l=1;l<=n;l=r+1)
    {
        while ((r<n) && (edge[r+1].w==edge[l].w)) r++;
        rep(j,l,r)
        {
            int x=edge[j].u,y=edge[j].v,
                fx=find(x),fy=find(y);
            if (fx!=fy) vis[edge[j].id]=1;
        }
        rep(j,l,r)
        {
            int x=edge[j].u,y=edge[j].v,
                fx=find(x),fy=find(y);
            if (fx!=fy) {fa[fx]=fy;ans+=edge[j].w;}
        }
    }
    int cnt=0;
    rep(i,1,n) if (vis[i]) cnt++;
    printf("%lld %d\n",ans,cnt);
    rep(i,1,n) if (vis[i]) printf("%d ",i);
    return 0;
} 

codeforces1137D Cooperative Game

学不来告辞

利用floyd和pollard-rho中的判圈方式,我们让\(0\)号棋子一次走一步,\(1\)号棋子两次走一步,直到两者相遇

我们假设此时\(1\)号棋子走了\(T+x\)步,那么\(0\)号棋子走了\(2(T+x)\)步

且应有\(T+x\equiv 0(mod\ C)\)

因此\(0\)和\(1\)号这两颗棋子再走\(T\)步即可到达终点

且剩下的\(8\)棵棋子需要走一条链的长度,也是\(T\)步

于是我们可以在\(2x+3T\)的步数内完成这一过程,由于\(x<C\),所以总步数小于\(3(T+C)\)

#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define lowbit(x) (x)&(-x)
#define rep(i,a,b) for (int i=a;i<=b;i++)
#define per(i,a,b) for (int i=a;i>=b;i--)
#define maxd 1000000007
typedef long long ll;
const int N=100000;
const double pi=acos(-1.0);
char s[20];

int read()
{
    int x=0,f=1;char ch=getchar();
    while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    return x*f;
}

int get_num()
{
    int ans=read();
    rep(i,1,ans) scanf("%s",s);
    return ans;
}

int main()
{
    while (1)
    {
        printf("next 0\n");fflush(stdout);
        int cnt=get_num();
        printf("next 0 1\n");fflush(stdout);
        cnt=get_num();
        if (cnt==2) break;
    }
    while (1)
    {
        printf("next 0 1 2 3 4 5 6 7 8 9\n");fflush(stdout);
        int cnt=get_num();
        if (cnt==1) break;
    }
    printf("done\n");fflush(stdout);
    return 0;
}

原文地址:https://www.cnblogs.com/zhou2003/p/10739708.html

时间: 2024-10-29 19:53:32

codeforces选做的相关文章

[SDOI2016]部分题选做

听说SDOI蛮简单的,但是SD蛮强的.. 之所以是选做,是因为自己某些知识水平还不到位,而且目前联赛在即,不好花时间去学sa啊之类的.. bzoj4517 数论题,我这种不会错排的数论白痴都能手推出来,这题应该谁都能写吧. #include<cstdio> #include<cstring> #include<algorithm> #define mo 1000000007 #define ll long long #define N 1000100 using nam

20165201 课下作业第十周(选做)

#20165201 课下作业第十周(选做) 相关知识点总结 补做代码运行结果截图 补做代码链接 相关知识点的总结 课上内容的补做,结果截图 教材第十五章的代码分析 补做教材第十五章的编程题目 提交补做的博客作业的连接 主动找老师进行作业答辩 原文地址:https://www.cnblogs.com/cbmwtsl/p/9000384.html

20165334 第十三周选做

20165334 第十三周选做 设计并实现一个Book类,定义义成Book.java,Book 包含书名,作者,出版社和出版日期,这些数据都要定义getter和setter. 定义至少三个构造方法,接收并初始化这些数据.覆盖(Override)toString方法,返回良好的含有多行的书的描述信息.覆盖equals方法,书名,作者,出版社和出版日期完全一致才说明两本书是一样的. 创建一个测试类Bookshelf, 其中的main方法创建并更新几个Book对象.Book至少包含三本本学期教材内容.

20175312 2018-2019-2 《Java程序设计》第6周课下选做——类定义

20175312 2018-2019-2 <Java程序设计>第6周课下选做--类定义 设计思路 1.我觉得Book其实就是一个中转的作用,由测试类Bookself通过Book输入数据,然后在验证通过后再取出. 2.在Book.java中储存测试类中输入的数据,然后验证信息是否一样,一样则输出,否则就返回false. 测试代码 Bookself.java public class Bookself { public static void main(String[] args) { Book

类定义(课下选做)

类定义(课下选做) 要求 Book类包含书名,作者,出版社和出版日期 数据都要定义getter和setter 至少三个构造方法,接收并初始化这些数据 覆盖toString方法,返回良好的含有多行的书的描述信息 覆盖equals方法,书名.作者.出版社和出版日期完全相同说明两本书相同. 创建一个测试类BookShelf 思路 根据要求最好分为两个类,即Book和BookShelf 在Book类中定义四个getter,返回书名.作者.出版社和出版日期 在BookShelf类中定义四个setter,赋

20175314薛勐 程序设计中临时变量的使用(课下测试,选做)

程序设计中临时变量的使用(课下测试,选做) 要求 定义一个数组:int arr[] = {1,2,3,4,5,6,7,8}; 打印原始数组的值:for(int i:arr){System.out.print(i + " "); } System.out.println();// 添加代码删除上面数组中的5 ... 打印出 1 2 3 4 6 7 8 0:for(int i:arr){System.out.print(i + " ");} System.out.pri

20175314薛勐 数据结构-排序(选做)

数据结构-排序(选做) 要求 在数据结构和算法中,排序是很重要的操作,要让一个类可以进行排序,有两种方法: 有类的源代码,针对某一成员变量排序,让类实现Comparable接口,调用Collection.sort(List) 没有类的源代码,或者多种排序,新建一个类,实现Comparator接口 调用Collection.sort(List, Compatator) 针对下面的Student类,使用Comparator编程完成以下功能: 在测试类StudentTest中新建学生列表,包括自己和学

数据结构-排序(选做) 20175204

数据结构-排序(选做) 任务要求 在数据结构和算法中,排序是很重要的操作,要让一个类可以进行排序,有两种方法: 有类的源代码,针对某一成员变量排序,让类实现Comparable接口,调用Collection.sort(List) 没有类的源代码,或者多种排序,新建一个类,实现Comparator接口 调用Collection.sort(List, Compatator) 针对下面的Student类,使用Comparator编程完成以下功能: 在测试类StudentTest中新建学生列表,包括自己

20175209 《MySort》和《IO-myhead》选做

20175209 <MySort>和<IO-myhead>选做 一.MySort 1.题目要求 模拟实现Linux下Sort -t : -k 2的功能. 要有伪代码,产品代码,测试代码(注意测试用例的设计) 参考 Sort的实现.提交博客链接. 2.设计思路 题目中要求为对第二列进行排序,个人设计时希望能够控制对所有列进行排序,因此需要在命令行中输入待排序的列号(这里存在一些小问题在后面问题中说明) 对于给定的字符数组无法直接进行排序,采用split方法将每一行分解后将带排序的列中