Codeforces Round #360 (Div. 2) D 数学推导 E dp

Posted 掉血菜鸡煮熟中

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #360 (Div. 2) D 数学推导 E dp相关的知识,希望对你有一定的参考价值。

Codeforces Round #360 (Div. 2)

A  ==

B  水,但记一下: 

第 n 个长度为偶数的回文数是  n+reverse(n)。

C    dfs 01染色,水

技术分享
#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
const int N = 200005;

int n, m;
struct Edge{int to,next; } e[N<<1];
int tot, head[N], mp[N<<1];
void Addedge(int u, int v) {
    mp[tot]=tot;    e[tot]={v, head[u] }; head[u]=tot++;
    mp[tot]=tot-1;  e[tot]={u, head[v] }; head[v]=tot++;
}
bool vis[N];
int cnt1, mark[N];
bool dfs(int u, bool flag)
{
    vis[u]=1,  mark[u]=flag;
    if(mark[u]==0) ++cnt1;
    for(int i=head[u]; i!=-1; i=e[i].next)
        if(mark[e[i].to]==-1)
        {
            bool flag1=dfs(e[i].to, flag^1);
            if(flag1==false) return false;
        }
        else if(mark[e[i].to]==flag)
        {
            return false;
        }
    return true;
}
int main()
{
    scanf("%d %d", &n, &m);
    int u, v;
    mes(head, -1);  mes(mark, -1);
    rep(i,1,m) {
        scanf("%d %d", &u, &v);
        Addedge(u, v);
    }
    rep(i,1,n) if(vis[i]==0) {
        bool flag=dfs(i, 0);
        if(flag==false) return 0*printf("-1");
    }
    printf("%d\n", cnt1);
    rep(i,1,n) if(mark[i]==0) printf("%d ", i);
    puts("");
    printf("%d\n", n-cnt1);
    rep(i,1,n) if(mark[i]==1) printf("%d ", i);
    puts("");

    return 0;
}
View Code

D    数学推导

题意:给出 k 但不告诉你 x ,并且告诉你 n 个 ci ,你也知道 x%ci, 问 x%k 是否能唯一确定。
tags: 这个题,完全懵的,题目意思都看不懂。。

反过来想,如果 x%k 不能唯一确定,则必定存在 x1、x2 (x1>x2) 满足 x1%ci==x2%ci,且 x1%k != x2%k 。 也就是 (x1-x2)%ci==0,且 (x1-x2)%k != 0 , 进一步说就是: lcm(ci) %(x1-x2)==0 且 lcm(ci)%k != 0 , 也就是 lcm(ci)%k != 0 。   这样就得出命题: 如果 x%k 不能唯一确定,那么 lcm(ci)%k != 0。  变为逆否命题即:如果 lcm(ci)%k==0 ,那么 x%k 能唯一确定。

技术分享
#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
const int N = 1000005;

ll  n, k, c[N];
int main()
{
    scanf("%lld %lld", &n, &k);
    ll  lcm1=1;
    rep(i,1,n) {
        scanf("%lld", &c[i]);
        if(lcm1) ( lcm1 = c[i]*lcm1/__gcd(c[i], lcm1) ) %=k;
        else  break;
    }
    if(lcm1%k==0) puts("Yes");
    else puts("No");

    return 0;
}
View Code

E     三维dp

题意: 给你一些硬币,让你选出一个子集的总价值和为 k,然后对于一个选出的子集,除了可以组成k以外,还可以在选出的子集中选出一些其他的价值。问你所有的选出的子集一共可以得到多少种价值。 

tags:  CF 评测机我是服气的,1.25e8 两秒的时限,这都能过。。

dp[i][j][k] 表示前 i 个硬币,当前遍历到第 i 个硬币时,选出的集合的总和是 j ,子集合的和是 k 的方案数。 递推式: dp[i][j][k] = dp[i-1][j]+dp[i-1][j-ci][k]+dp[i-1][j-ci][k-ci] 。(即遍历到第 i 个硬币时,可以不选它,也可以选它加入到总集合,但不加入子集合, 也可选它加入到两个集合)

技术分享
#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
const int N = 501;

int n, ki, c[N];
ll  dp[2][N][N];
int main()
{
    scanf("%d %d", &n, &ki);
    rep(i,1,n) scanf("%d", &c[i]);
    int cnt=0;      dp[cnt^1][0][0] = 1;
    rep(i,1,n)
    {
        rep(j,0,ki) rep(k,0,j)
        {
            dp[cnt][j][k]=0;
            dp[cnt][j][k] = max(dp[cnt][j][k], dp[cnt^1][j][k]);
            if(j-c[i]>=0) dp[cnt][j][k] = max(dp[cnt][j][k], dp[cnt^1][j-c[i]][k]);
            if(k-c[i]>=0) dp[cnt][j][k] = max(dp[cnt][j][k], dp[cnt^1][j-c[i]][k-c[i]]);
        }
        cnt ^= 1;
    }
    cnt ^= 1;
    int ans=0;
    rep(k,0,ki) if(dp[cnt][ki][k]) ++ans;
    printf("%d\n", ans);
    rep(k,0,ki) if(dp[cnt][ki][k]) printf("%d ", k);
    puts("");

    return 0;
}
View Code

以上是关于Codeforces Round #360 (Div. 2) D 数学推导 E dp的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #360 C

Codeforces Round #360 D

Codeforces Round #360 E

Codeforces Round #360 (Div. 2) D 数学推导 E dp

Codeforces Round #360 (Div. 1) D. Dividing Kingdom II 并查集求奇偶元环

Codeforces Round #360 (Div. 2) C D E