[Baltic2014]sequence 解题报告

想了很久还是不会。。然后开始各种乱搞全都不行。。

最后看了题解感觉好厉害!

首先我们将问题放缩。设x的每一位的数字集合是S(x),则对于给定数列{Bi}(i∈[0,k)),Bi∈{0,1,2,3,4,5,6,7,8,9},?i∈[0,k),要求Bi∈S(n+i),求最小的n。

这样的话,如果我们枚举n的个位,就会将问题转化为10个k10规模的问题!

当k=1时,显然就可以直接贪心了。

所以时间复杂度就是O(10?klog10k)的。

但是还有不少非常蛋碎的细节。。

当k=2的时候,我们可能会选择让个位=9,但是这样的话k的规模就不会缩小了,不过显然我们连续枚举两个9是毫无卵用的。所以这里我们需要特判。

还有前缀0,如果前缀0中有一个0存在是在它还没有发生任何+1的时候产生了贡献,那么我们就需要在最前面补1;否则的话就不需要。

贪心的时候有0的话也很麻烦,因为如果只有它自己,就应该在前面加10,否则的话就应该加在最前面那个数的后面。

我在乱搞的时候以为只有当我选这一位会产生贡献的时候才选这一位,然而其实并不是。

比如说

2

2 2

答案应该是20,个位的0并未产生任何贡献。

代码:

#include<cstdio>
#include<iostream>
using namespace std;
#include<algorithm>
#include<cstdlib>
#include<cmath>
const int K=1e5+5,N=1e6+5;
typedef long long LL;
int pos[10][K];
bool exist[N][10];
int f[N][10];
int k;
int check(int n,int x,int cur,int Mod){
    //if(n==8)printf("check(%d,%d)\n",n,x);
    for(int i=cur;i;--i){
        /*if(n==8){
            printf("%d:%d\n",n+pos[x][i],exist[n+pos[x][i]][x]);
        }*/
        if(x?!exist[(n+pos[x][i])%Mod][x]:!(exist[(n+pos[x][i])%Mod][0]||(n+pos[x][i])%Mod<Mod/10))
            return i;
    }
    //if(n==102451)printf("check(%d,%d)=%d\n",n,x,1);
    return 0;
}
int main(){
    freopen("bzoj_3917.in","r",stdin);
    //freopen("bzoj_3917_test.out","w",stdout);
    int x;

    exist[0][0]=1;
    for(int i=1;i<N;++i)
        for(x=i;x;x/=10)
            exist[i][x%10]=1;

    /*for(int i=1;i<=100;++i){
        printf("%d:",i);
        for(int j=0;j<10;++j)printf("%d",exist[i][j]);
        puts("");
    }*/

    scanf("%d",&k);
    int b;
    for(int i=0;i<k;++i){
        scanf("%d",&b);
        pos[b][++pos[b][0]]=i;
    }

    for(int i=10;i--;)random_shuffle(pos[i]+1,pos[i]+pos[i][0]+1);

    LL ans=1e18;
    LL prod;
    LL now;
    LL power=1;

    for(int n=0;n<10;++n){
        //printf("---%d---\n",n);
        if(n==power*10)power*=10;
        prod=1e6;
        now=n;
        for(int i=10;i--;)f[n][i]=pos[i][0];
        for(int i=9;now<ans&&i;--i)
            if(f[n][i]=check(n,i,pos[i][0],10)){
                now+=prod*i;
                prod*=10;
            }
        if(now<ans)
            if(f[n][0]=check(n,0,pos[0][0],10)){
                if(prod>1e6){
                    x=now/(prod/10);
                    now-=x*(prod/10);

                    now+=x*prod;
                }
                else now+=prod*10;
            }
        if(now)ans=min(ans,now);

        /*if(n==8)
            for(int i=0;i<10;++i)
                printf("f(%d)=%d\n",i,f[n][i]?pos[i][f[n][i]]:0);*/
    }

    for(int n=10;n<101;++n){
        //printf("---%d---\n",n);
        if(n==power*10)power*=10;
        prod=1e6;
        now=n;
        for(int i=10;i--;)f[n][i]=f[n%power][i];
        for(int i=9;now<ans&&i;--i)
            if(f[n][i]=check(n,i,f[n%power][i],power*10)){
                now+=prod*i;
                prod*=10;
            }
        if(now<ans)
            if(f[n][0]=check(n,0,f[n%power][0],power*10)){
                if(prod>1e6){
                    x=now/(prod/10);
                    now-=x*(prod/10);

                    now+=x*prod;
                }
                else now+=prod*10;
            }
        if(now)ans=min(ans,now);

        //if(n==90)cout<<now<<endl;

        /*if(n==8)
            for(int i=0;i<10;++i)
                printf("f(%d)=%d\n",i,f[n][i]?pos[i][f[n][i]]:0);*/
    }
    cout<<ans<<endl;
    //cout<<tot<<endl;
}

总结:

①有时将原问题松弛也往往会有奇效。

②特殊情况一定要想清楚。

时间: 2024-10-11 06:16:57

[Baltic2014]sequence 解题报告的相关文章

hdu 1711 Number Sequence 解题报告

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1711 题目意思:给出一条有n个数的序列a[1],a[2],......,a[n],和一条有m 个数的序列b[1],b[2],......,b[m],求出b[1],b[2],...,b[m]在序列a中完全匹配时,在序列a中的位置,如果找不到输出-1. 这几天一直在学kmp,该题算是kmp的入门题吧.有个地方要稍稍注意,代码中,主串和模式串的比较初始值为-1,-1,否则如果从0开始,会默认第一个字符是相

USACO Section2.1 Sorting a Three-Valued Sequence 解题报告

sort3解题报告 —— icedream61 博客园(转载请注明出处)------------------------------------------------------------------------------------------------------------------------------------------------[题目] 给你N,而后给出N个数,每个数都是1~3中的一个.请问,要把这个数列升序排好,最少需要进行几次两两交换?[数据范围] 1<=N<

Ducci Sequence解题报告

A Ducci sequence is a sequence of n-tuples of integers. Given an n-tuple of integers (a1, a2, ... , an), the next n-tuple in the sequence is formed by taking the absolute differences of neighboring integers: ( a1, a2, ... , an)  (| a1 - a2|,| a2 - a3

【LeetCode】Longest Consecutive Sequence 解题报告

[题目] Given an unsorted array of integers, find the length of the longest consecutive elements sequence. For example, Given [100, 4, 200, 1, 3, 2], The longest consecutive elements sequence is [1, 2, 3, 4]. Return its length: 4. Your algorithm should

Winter-1-F Number Sequence 解题报告及测试数据

Time Limit:1000MS     Memory Limit:32768KB Description ?A number sequence is defined as follows:f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7.Given A, B, and n, you are to calculate the value of f(n). Input The input consists of mult

LeetCode: Permutation Sequence 解题报告

Permutation Sequence https://oj.leetcode.com/problems/permutation-sequence/ The set [1,2,3,…,n] contains a total of n! unique permutations. By listing and labeling all of the permutations in order, We get the following sequence (ie, for n = 3): "123&

LeetCode: Longest Consecutive Sequence 解题报告

Longest Consecutive Sequence Given an unsorted array of integers, find the length of the longest consecutive elements sequence. For example,Given [100, 4, 200, 1, 3, 2],The longest consecutive elements sequence is [1, 2, 3, 4]. Return its length: 4.

Hdu 5064 Find Sequence 解题报告

题目出处:http://acm.hdu.edu.cn/showproblem.php?pid=5064 题意:给定n个数,求满足以下两个条件的子序列的最大长度: (1)C1<C2<C3<......<Ct; (2)C2-C1<C3-C2<......<Ct-Ct-1. 分析:解结构一定为为N1,N1,N1,......,N1,N2,N3,......,Nt   设dp[i][j]表示以num[i], num[j]结尾的有效序列的长度,则有         dp[i

UVa -1584 Circular Sequence 解题报告

1.题目大意 输入长度为n$(2\le n\le 100)$的环状DNA串,找出该DNA串字典序最小的最小表示. 2.思路 这题特别简单,一一对比不同位置开始的字符串的字典序,更新result. 3.代码 #include"stdio.h" #include"string.h" #define maxn 100 int judge(char* s,int p,int q) //比较p的字典序是否比q小 { int m=strlen(s); for(int i=0;