Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 2259 | Accepted: 820 |
Description
The safe will open as soon as the last digit of the correct code is entered. There is no "enter" key. When you enter more than n digits, only the last n digits are significant. For example (in the 4-digit version), if the correct code is 4567, and you plan to enter the digit sequence 1234567890, the door will open as soon as you press the 7 key.
The software to create this effect is rather simple. In the n-digit version the safe is always in one of 10n-1 internal states. The current state of the safe simply represents the last n-1 digits that have been entered. One of these states (in the example above, state 456) is marked as the unlocked state. If the safe is in the unlocked state and then the right key (in the example above, 7) is pressed, the door opens. Otherwise the safe shifts to the corresponding new state. For example, if the safe is in state 456 and then you press 8, the safe goes into state 568.
A trivial strategy to open the safe is to enter all possible codes one after the other. In the worst case, however, this will require n * 10n keystrokes. By choosing a good digit sequence it is possible to open the safe in at most 10n + n - 1 keystrokes. All you have to do is to find a digit sequence that contains all n-digit sequences exactly once. KEY Inc. claims that for the military version (n=6) the fastest computers available today would need billions of years to find such a sequence - but apparently they don't know what some programmers are capable of...
Input
Output
Sample Input
1 2 0
Sample Output
0123456789 00102030405060708091121314151617181922324252627282933435363738394454647484955657585966768697787988990
Source
呃其實剛做這個題是20多天前了。。當時就不會 現在終於會了 竟然是圖論的題
題目大意是:
你需要輸入n位的密碼 如果前n-1位對了 第n位也對的話 就打開了
否則此時的後n-1位變成了前n-1位 等待最後一位的輸入 依次下去 題目要求給出按鍵的順序 使得字典序最小
相當於給出一串數組序列 有一個長度爲n的窗戶 從1-n開始 每次後移一個格
如樣例
2
00102030405060708091121314151617181922324252627282933435363738394454647484955657585966768697787988990依次是00 01 10 02 20 03 30 04 ... 80 09 91 11 12 21 13 .... 90
如果從n個0 到n個9 一個一個試的話 最壞情況是n*10^n次
給出的答案長度是10^n+n-1 如果每一次的數字都不重複的話 而且兩個數之間共享了n-1位相同的數字
窗口每向後滑一次 產生一個新的數 一共10^n個數 滑了10^n-1次 加上第一個數的長度n 所以答案一共10^n+n-1個數字
而所有數字要求出現且僅出現1次
把每個數字轉化爲邊 每個數前n-1位到後n-1位之間有一條邊 求圖的歐拉回路
而且還要用非遞歸寫。。第一次寫模擬遞歸用的goto
#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
struct self
{
int x,y,nxt;
}s[3000001];
int fst[100001];
int flag[3000001];
int ret[3000001];
int ans;
int m,n,x,y;
int lim;
void calc(int k)
{
lim=1;
k--;
n=0;
memset(flag,0,sizeof(flag));
memset(fst,-1,sizeof(fst));
ans=0;
while(k)
{
k--;
lim*=10;
}
}
void add(int x,int y)
{
n++;
s[n].x=x;
s[n].y=y;
s[n].nxt=fst[x];
fst[x]=n;
}
struct node
{
int u,e;
}st[3000001];
int top;
void dfs()
{
top=1;
st[1].u=0;
st[1].e=-1;
a:
while(top)
{
node u=st[top];
for(int e=fst[u.u];e!=-1;e=s[e].nxt)
{
if(!flag[e])
{
flag[e]=1;
top++;
st[top].u=s[e].y;
st[top].e=e;
goto a;
}
}
top--;
ans++;
ret[ans]=u.e;
}
}
inline void out(int x)
{
if(x>9)
out(x/10);
putchar(x%10+'0');
}
int main()
{
//freopen("1.out","w",stdout);
while(scanf("%d",&m)==1 && m)
{
if(m==1)
{
printf("0123456789\n");
continue;
}
calc(m);
int tt=lim/10;
for(int i=0;i<lim;i++)
for(int j=9;j>=0;j--)
{
x=i;
y=x%tt*10+j;
add(x,y);
}
dfs();
/*
for(int i=1;i<m;i++)printf("0");
for(int i=ans-1;i>=1;i--)
printf("%d",s[ret[i]].y%10);
printf("\n");
*/
for(int i=1;i<m;i++)out(0);
for(int i=ans-1;i>=1;i--)
out(s[ret[i]].y%10);
printf("\n");
}
return 0;
}
不用輸出外掛
加上輸出外掛 G++竟然比C++還快