序列A由从N开始的连续K个数按顺序构成,现在将A中的每个数只保留某一个数码,记为序列B,给定K和B,求可能的最小的N
标签:
APIO2016练习赛第二题
对于一个数,会有一些数必须要填,我们用一个二进制数来记录这些限制。
我们考虑从低到高依次处理每一位,对于每一位枚举所有数,然后递推得到下一位的限制信息,这样直到处理到最后。
有一种情况比较特殊,n≤2&&i==9的时候下一位不能填9,否则会停不下来,算是一个搜索的终止状态。
#include<iostream> #include<cstdlib> #include<cmath> #include<cstring> #include<cstdio> #include<algorithm> #define F(i,j,n) for(int i=j;i<=n;i++) #define D(i,j,n) for(int i=j;i>=n;i--) #define ll long long #define maxn 100005 using namespace std; int a[maxn]; inline 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; } inline ll solve(int *a,int n,int flag) { ll ret=1ll<<60; if (n==1) { ret=0; F(i,1,9) if (a[1]&(1<<i)) { ret=ret*10+i; if (ret==i&&(a[1]&1)) ret*=10; } if (ret==0&&(a[1]&1)) ret=10; return ret; } int b[maxn],cnt=0; F(i,0,9) { if (i==9&&!flag) break; int num=0,now=i;cnt=0;bool p=false; F(j,1,n) { num|=a[j]&(1023-(1<<now)); if ((a[j]&1)&&now==0) p=true; now=(now+1)%10; if (!now||j==n) b[++cnt]=num,num=0; } ll ans=solve(b,cnt,i<9||n>2)*10+i; if (!ans&&p) ans=10; ret=min(ret,ans); } return ret; } int main() { int n=read(); F(i,1,n) a[i]=1<<read(); printf("%lld\n",solve(a,n,1)); }
标签:
原文地址:http://blog.csdn.net/aarongzk/article/details/51368021