codeforces - 808 (div2)

A.把这个数+1,如果符合条件就符合条件了,不符合就把最高位 + 1,其余位置0

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <bitset>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)  
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))  
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x)  
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x)  
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long  
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second 
typedef vector<int> VI;
int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();}
while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;}
const double eps = 1e-9;
const int maxn = 110;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7; 
LL N,M,K;
int cul(LL x){
    int ans = 0;
    while(x){
        if(x % 10) ans++;
        x /= 10;
    }
    return ans;
}
int main(){
    Scl(N);
    LL x = N + 1;
    int num = cul(x);
    if(num == 1){
        Pri(1);
        return 0;
    }
    int p = 0;
    do{
        p++;
        x /= 10;
    }while(x >= 10);
    x++;
    for(int i = 0 ; i < p ;i ++) x *= 10;
    Prl(x - N);
    return 0;
}
A

 

B.列几下就找到规律,每个数加的次数是呈阶梯状的,例如 1 2 3 3 3 3 3 2 1,阶梯顶的值由星期数和K的最小值决定

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <bitset>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)  
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))  
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x)  
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x)  
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long  
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second 
typedef vector<int> VI;
int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();}
while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;}
const double eps = 1e-9;
const int maxn = 2e5 + 10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7; 
int N,M,K;
long double a[maxn];
int main(){
    Sca2(N,M);
    long double sum = 0;
    for(int i = 1; i <= N; i ++){
        scanf("%Lf",&a[i]); 
        sum += a[i] * min(min(min(i,N - i + 1),M),N - M + 1);
    } 
    printf("%.10Lf",sum / (N - M + 1));
    return 0;
}
B

 

C.先全部装一半,然后从大杯子往小杯子依次把剩下的水倒完,倒不完的和水不够的都是有问题的

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <bitset>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)  
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))  
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x)  
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x)  
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long  
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second 
typedef vector<int> VI;
int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();}
while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;}
const double eps = 1e-9;
const int maxn = 110;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7; 
int N,M,K;
PII a[maxn];
int b[maxn];
int ans[maxn];
int main(){
    Sca2(N,M); int sum = 0;
    for(int i = 1; i <= N ; i ++) Sca(a[i].fi),a[i].se = i;
    sort(a + 1,a + 1 + N);
    for(int i = 1; i <= N ; i ++){
        b[i] = a[i].fi / 2;
        if(a[i].fi & 1) b[i]++;
        M -= b[i];
    }
    if(M < 0){
        puts("-1");
        return 0;
    } 
    for(int i = N; i >= 1 && M; i --){
        int t = min(a[i].fi - b[i],M);
        b[i] += t;
        M -= t;
    }
    if(M){
        puts("-1");
        return 0;
    }
    for(int i = 1; i <= N ; i ++) ans[a[i].se] = b[i];
    for(int i = 1; i <= N ; i ++){
        printf("%d ",ans[i]);
    }
    return 0;
}
C

 

D.求出前缀和,枚举移动的数字t,然后二分在数字左端寻找pre[i] + t = sum的i,二分在右寻找pre[i] - t = sum的i

找到一次就是YES

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <bitset>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)  
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))  
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x)  
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x)  
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long  
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second 
typedef vector<int> VI;
int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();}
while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;}
const double eps = 1e-9;
const int maxn = 1e5 + 10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9; 
int a[maxn];
LL pre[maxn];
int N;
LL sum;
bool check(int t)
{
    int l = 0;
    int r = t - 1;
    while(l <= r){
        int mid = (l + r) / 2;
        if(pre[mid] + a[t] < sum) l = mid + 1;
        else if(pre[mid] + a[t] > sum) r = mid - 1;
        else return true;
    }
    l = t; r = N;
    while(l <= r){
        int mid = (l + r) / 2;
        if(pre[mid] - a[t] < sum) l = mid + 1;
        else if(pre[mid] - a[t] > sum) r = mid - 1;
        else return true;
    }
    return false;
    
}
int main()
{
    Sca(N);
    sum = 0;
    for(int i = 1; i <= N ; i ++){
        scanf("%d",&a[i]);
        sum += a[i];
        pre[i] = pre[i - 1] + a[i];
    }
    if(sum & 1){
        printf("NO\n");
        return 0;
    }
    sum /= 2; bool flag = 0;
    for(int i = 1; i <= N && !flag; i ++) if(check(i)) flag = 1;
    if(flag) printf("YES\n");
    else printf("NO\n");
    return 0;
}
D

 

E.感觉是个dp,我的做法肯定不是正解。

把三种重量的背包分类,按照价值从大到小排序然后求出前缀和,那么一定是在1,2,3中选择a,b,c个物品,答案是pre[a] + pre[b] + pre[c]

但是枚举是个O(n²),不能直接做。

所以直接上了模拟退火,模拟a,b,c指针的移动寻找最大值,洗了洗手交了一发就AC了

注:交下面的代码一遍可能A不了,需要洗洗手多交一边

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <bitset>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)  
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))  
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x)  
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x)  
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long  
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second 
typedef vector<int> VI;
int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();}
while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;}
const double eps = 1e-9;
const int maxn = 1e5 + 10;
const int maxm = 3e5 + 10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7; 
int N,M,K;
LL pre[4][maxn],cnt[4];
vector<LL>Q[4];
bool cmp(LL a,LL b){
    return a > b;
}
LL ans,ansa,ansb,ansc;
LL cul(LL a,LL b,LL c){
    if(a + 2 * b + 3 * c > M) return 0;
    return pre[1][a] + pre[2][b] + pre[3][c];
}
const double delta = 0.999;
void s_a(){
    double t = 30000;
    int a = ansa,b = ansb,c = ansc;
    while(t > 1e-14){
        int atmp = a + (rand() * 2 - RAND_MAX) * t; atmp = ((atmp % (Q[1].size() + 1)) + Q[1].size() + 1) % (Q[1].size() + 1);
        int btmp = b + (rand() * 2 - RAND_MAX) * t; btmp = ((btmp % (Q[2].size() + 1)) + Q[2].size() + 1) % (Q[2].size() + 1);
        int ctmp = c + (rand() * 2 - RAND_MAX) * t; ctmp = ((ctmp % (Q[3].size() + 1)) + Q[3].size() + 1) % (Q[3].size() + 1);
        LL new_ans = cul(atmp,btmp,ctmp);
        LL DE = new_ans - ans;
        if(DE > 0){
            ansa = a = atmp; ansb = b = btmp; ansc = c = ctmp;
            ans = new_ans;
        }else if(-exp(-DE / t) * RAND_MAX > rand()){
            a = atmp; b = btmp; c = ctmp;
        }
        t = t * delta;
    }
}
void SA(){
    s_a();s_a();
    s_a();s_a();
    s_a();s_a();
}
int main(){
    Sca2(N,M); srand(time(NULL));
    for(int i = 1; i <= N ; i ++){
        LL w = read(),t = read();
        Q[w].pb(t);
    }
    for(int i = 1; i <= 3; i ++) sort(Q[i].begin(),Q[i].end(),cmp);
    for(int i = 1; i <= 3; i ++){
        for(int j = 0 ; j < Q[i].size(); j ++){
            pre[i][j + 1] = pre[i][j] + Q[i][j];
        }
    }
    ansa = ansb = ansc = 0;
    SA(); //ACACAC
    Prl(cul(ansa,ansb,ansc));
    return 0;
}
E

 

F.题目的导向很明显,二分level或者将level排序依次更新答案。

先考虑2分level,如果将题目的意思换一种方式说:对于ci和为质数的两张卡片,必须至少放弃其中一张。

再配上N这个100的范围,思路就呼之欲出了

这是一个类似最大权闭合子图的网络流,建图的方法稍微和最大权闭合子图有些出入

拆所有点i为i和i + N

将所有点S向i连边,容量为p,将所有点i + N向T连边,然后对于每一对和为质数的点i,j,从i - j + N连边,容量为INF

最后整张图最大流的一半就是不得不放弃的最小权值,将总权值减去他和K比较即可check成功

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <bitset>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)  
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))  
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x)  
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x)  
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long  
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second 
typedef vector<int> VI;
int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();}
while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;}
const double eps = 1e-9;
const int maxn = 1010;
const int maxm = 2e5 + 10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7; 
int N,M,K;
bool isprime[maxm];
void init(){
    for(int i = 2; i < maxm; i ++) isprime[i] = 1;
    for(int i = 2; i < maxm;  i ++){
        if(!isprime[i]) continue;
        for(int j = i + i; j < maxm; j += i){
            isprime[j] = 0;
        }
    }
}
struct Dinic{
    struct Edge{
        int from,to,next,cap,flow;
        Edge(){}
        Edge(int from,int to,int next,int cap,int flow):from(from),to(to),next(next),cap(cap),flow(flow){}
    }edge[maxm * 2];  
    int n,s,t,head[maxn],tot;
    int dep[maxn],cur[maxn];
    void init(int n,int s,int t){
        this->n = n; this->s = s; this->t = t; 
        tot = 0;
        for(int i = 0 ; i <= n ; i ++) head[i] = -1;
    }
    inline void add(int s,int t,int w){
        //cout << s << ' ' << t << " " << w << endl;
        edge[tot] = Edge(s,t,head[s],w,0);
        head[s] = tot++;
        edge[tot] = Edge(t,s,head[t],0,0);
        head[t] = tot++;
    }
    inline bool BFS(){
        for(int i = 0 ; i <= n ; i ++) dep[i] = -1;
        dep[s] = 1;
        queue<int>Q; Q.push(s);
        while(!Q.empty()){
            int u = Q.front(); Q.pop();
            for(int i = head[u]; ~i ; i = edge[i].next){
                int v = edge[i].to;
                if(~dep[v] || edge[i].flow >= edge[i].cap) continue;
                dep[v] = dep[u] + 1;
                Q.push(v);
            }
         }
         return ~dep[t];
    }
    inline int DFS(const int& u,int a){
        if(u == t || !a) return a;
        int flow = 0;
        for(int &i = cur[u]; ~i ; i = edge[i].next){
            int v = edge[i].to;
            if(dep[v] != dep[u] + 1) continue;
            int f = DFS(v,min(a,edge[i].cap - edge[i].flow));
            if(!f) continue;
            edge[i ^ 1].flow -= f;
            edge[i].flow += f; 
            a -= f;
            flow += f;
        }
        return flow;
    }
    inline int maxflow(){
        return maxflow(s,t);
    }
    inline int maxflow(int s,int t){
        int flow = 0;
        while(BFS()){
            for(int i = 0; i <= n ; i ++) cur[i] = head[i];
            flow += DFS(s,INF);
        }
        return flow;
    }
}g;
struct Node{
    int p,c,l;
}node[110];
bool cmp(Node a,Node b){
    return a.l < b.l;
}
bool check(int m){
    int S = N + N + 1,T = N + N + 2;
    g.init(T,S,T); LL sum = 0;
//    if(m == 4){
//        puts("bug");
//    }
    for(int i = 1; i <= N ; i ++){
        if(node[i].l > m) break;
        sum += node[i].p * 2;
        g.add(S,i,node[i].p); g.add(i + N,T,node[i].p);
        for(int j = 1; j <= N ; j ++){
            if(i == j) continue;
            if(node[j].l > m) break;
            if(isprime[node[i].c + node[j].c]) g.add(i,j + N,INF);
        }
    }
    int x = g.maxflow(); 
    return (sum - x) >= M * 2;
}
int solve(){
    int l = 1,r = N;
    int ans = -1;
    while(l <= r){
        int m = l + r >> 1;
        if(check(m)){
            ans = m;
            r = m - 1;
        }else{
            l = m + 1;
        }
    }
    return ans;
}
int main(){
    Sca2(N,M); init();
    for(int i = 1; i <= N ; i ++) Sca3(node[i].p,node[i].c,node[i].l);
    sort(node + 1,node + 1 + N,cmp);
    Pri(solve());
    return 0;
}
F

 

G.

dp[i]表示到这个[1 - i]范围内的字符串A最多可以匹配多少B,dp2[i]表示最后一个字符串是以i结尾的情况下,[1-i]范围内的字符串最多可以匹配多少B

那么先通过跳next指针的方式更新dp[2],然后dp[i] = max(dp[i - 1],dp2[i])

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <bitset>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)  
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))  
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x)  
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x)  
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long  
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second 
typedef vector<int> VI;
int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();}
while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;}
const double eps = 1e-9;
const int maxn = 1e5 + 10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
char A[maxn],B[maxn]; 
LL dp[maxn],dp2[maxn];
int nxt[maxn];
int N,M,K;
void kmp_pre(char x[],int m,int nxt[]){
    int j = 0;
    nxt[1] = 0;
    for(int i = 2; i <= m ; i ++){
        while(j && x[i] != x[j + 1]) j = nxt[j];
        if(x[j + 1] == x[i]) j ++;
        nxt[i] = j;
    }
}
int main(){
    scanf("%s%s",A + 1,B + 1);
    N = strlen(A + 1),M = strlen(B + 1);
    kmp_pre(B,M,nxt);
//    for(int i = 1; i <= M ; i ++){
//        cout << nxt[i] << " ";
//    }
//    cout << endl;
    for(int i = M; i <= N ; i ++){
        bool flag = 1;
        for(int j = 1; j <= M; j ++){
            if(B[j] != A[i - M + j] && A[i - M + j] != '?') flag = 0;
        }
        if(!flag){
            dp[i] = dp[i - 1];
            continue;
        } 
        dp2[i] = max(dp2[i],dp[i - M] + 1);
        for(int j = nxt[M]; j ; j = nxt[j]){
            dp2[i] = max(dp2[i],dp2[i - M + j] + 1);
        }
        dp[i] = max(dp[i - 1],dp2[i]);
    }
    Prl(dp[N]);
    return 0;
}
G

 

posted @ 2019-07-19 17:23  Hugh_Locke  阅读(356)  评论(0编辑  收藏  举报