正题
这题比较简单,但是题目好像出了一点锅,细节挺多的,调了很久。
发现n>=1e7的时候可以直接暴力枚举n的倍数,然后判断累加。
时,余数不会超过
,很容易可以想到Meet in the Middle。
我们枚举后七位的值,用表示第一位为i,第一位与第二位的大小关系为j,mod n余数为k而且可以作为一个波浪数的后缀的方案数。好好理解这一句话。这个数组很容易开爆,可以离散化一下,因为
以内的波浪数不超过
然后从小到大枚举前七位的值,计算答案即可。
注意几个细节:
1.首先一个波浪数的后缀仍然是一个波浪数。
2.以00开头的7位数不能作为一个波浪数的后缀,根据定义可得。
3.以0xy开头的7位数(x<y)不能作为一个波浪数的后缀。
4.根据定义可得,11,22,33,44,55,66,77,88,99,都是波浪数,但是数据里并不是这么认为的。
这四个细节都是一个下午刚出来的。Orz zch
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;
long long n,k;
int cnt[10][2][830200];
int hash[10000010],op;
bool check(long long x){
//if(!(x/100)) return true;
int first=x%10,next=(x/10)%10;
bool tf=first>next;//1Ϊ´óÓÚ£¬0ΪСÓÚ
if(first==next) return false;x/=100;
while(x){
int temp=x%10;
if(tf && temp<=next || !tf && temp>=next) return false;
tf^=true;next=temp;x/=10;
}
return true;
}
int main(){
scanf("%lld %lld",&n,&k);
if(n>=1e7){
int tot=0;
for(long long i=n;i<=1e14;i+=n){
if(check(i)) tot++;
if(tot==k) {
printf("%lld\n",i);
return 0;
}
}
printf("-1");
return 0;
}
long long tot=0,t=0;
for(int i=1;i<=1e7;i++){
if(check(i)){
if(i%n==0) tot++;
if(k==tot){
printf("%d\n",i);
return 0;
}
if(i/100000) {
if(i/1000000==0 && i/100000%10<=i/10000%10) continue;
if(!hash[i%n]) hash[i%n]=++op;
cnt[i/1000000][i/1000000>(i/100000%10)][hash[i%n]]++;
}
}
}
int m=0,data=10000000%n;
for(int i=1;i<=1e7;i++){
(m+=data)%=n;t=tot;
int tp=n-m;if(tp==n) tp=0;
if(!check(i) || !hash[tp]) continue;
if(i/10%10==i%10) continue;
if(i<10){
for(int j=0;j<i;j++) tot+=cnt[j][0][hash[tp]];
for(int j=i+1;j<=9;j++) tot+=cnt[j][1][hash[tp]];
}
else{
int temp=i%10;
if(i/10%10<temp) for(int j=0;j<temp;j++) tot+=cnt[j][0][hash[tp]];
else for(int j=temp+1;j<=9;j++) tot+=cnt[j][1][hash[tp]];
}
if(tot>=k){
for(long long j=(i*10000000ll+1)%n==0?i*10000000ll+1:(i*10000000ll+1)/n*n+n;j<(i+1)*10000000ll;j+=n){
if(check(j)) t++;
if(t==k){
printf("%lld\n",j);
return 0;
}
}
}
}
printf("-1");
}
3294

被折叠的 条评论
为什么被折叠?



