Codeforces Round #268 (Div. 1) C. Hack it! 数位dp + 构造数位
傳送門
文章目錄
- 題意:
- 思路:
題意:
定義f(x)f(x)f(x)表示xxx的十進制下數位和,現在給你aaa,讓你選一個區間[l,r][l,r][l,r],滿足∑i=lrf(i)moda=0\sum_{i=l}^rf(i)\bmod a=0∑i=lr?f(i)moda=0。
1≤a≤1e181\le a\le1e181≤a≤1e18
要求輸出的l,rl,rl,r滿足1≤l≤r≤102001\le l\le r\le 10^{200}1≤l≤r≤10200
思路:
考慮這樣一個事情,對于xxx,我們找一個10k>x10^k>x10k>x,那么此時f(10k+x)?f(x)=1f(10^k+x)-f(x)=1f(10k+x)?f(x)=1。
有了這個之后,我們自然的想構造出來aaa個這樣的對,這樣模aaa就是000了。
取一個比aaa大的101010的冪次101910^{19}1019,所以就會想到構造這樣的區間[a+1,1019+a][a+1,10^{19}+a][a+1,1019+a],轉換成前綴和的形式[1,1019+a]?[1,a][1,10^{19}+a]-[1,a][1,1019+a]?[1,a],顯然這是不行的,雖然這樣保證了[1,a],[1019+1,1019+a][1,a],[10^{19}+1,10^{19}+a][1,a],[1019+1,1019+a]兩個區間對應數fff做差為111,并且有aaa個這樣的數,但是忽略了[a+1,1019][a+1,10^{19}][a+1,1019]這段區間對答案的貢獻,那么既然去不掉這段區間,那么不妨將這段區間加入答案中,也就是我們上面說的aaa對這樣的數,假設多出來kkk,那么我們只需要添加a?ka-ka?k對即可,考慮這些多出來的怎么計算。
我們考慮求出來∑i=11019f(i)moda\sum_{i=1}^{10^{19}}f(i)\bmod a∑i=11019?f(i)moda,設其為kkk,換句話說,我們現在需要加上a?ka-ka?k個111就可以達到要求了。考慮將原本區間[1,1019][1,10^{19}][1,1019]不斷右移,比如右移一次[2,1019+1][2,10^{19}+1][2,1019+1],不難發現,這個時候原本的111的貢獻變成了1+10191+10^{19}1+1019的貢獻,增加了111,所以我們右移a?ka-ka?k次,得到區間[a?k+1,1019+a?k][a-k+1,10^{19}+a-k][a?k+1,1019+a?k],答案就是這個區間啦。
取一個比較大的101010的冪次,防止移動過程中超過這個冪次即可。
// Problem: C. Hack it! // Contest: Codeforces - Codeforces Round #268 (Div. 1) // URL: https://codeforces.com/problemset/problem/468/C // Memory Limit: 256 MB // Time Limit: 1000 ms // // Powered by CP Editor (https://cpeditor.org)//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native") //#pragma GCC optimize(2) #include<cstdio> #include<iostream> #include<string> #include<cstring> #include<map> #include<cmath> #include<cctype> #include<vector> #include<set> #include<queue> #include<algorithm> #include<sstream> #include<ctime> #include<cstdlib> #include<random> #include<cassert> #define X first #define Y second #define L (u<<1) #define R (u<<1|1) #define pb push_back #define mk make_pair #define Mid ((tr[u].l+tr[u].r)>>1) #define Len(u) (tr[u].r-tr[u].l+1) #define random(a,b) ((a)+rand()%((b)-(a)+1)) #define db puts("---") using namespace std;//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); } //void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); } //void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> PII;const int N=1000010,INF=0x3f3f3f3f; const double eps=1e-6;LL f[30][10*20],mod; int a[30];LL dp(int pos,LL sum,int flag) {if(pos==0) return sum%mod;if(f[pos][sum]!=-1&&flag) return f[pos][sum];int x=flag? 9:a[pos];LL ans=0;for(int i=0;i<=x;i++) (ans+=dp(pos-1,sum+i,flag||i<x))%=mod;if(flag) f[pos][sum]=ans;return ans; }LL solve() {// int tot=0;// while(x) a[++tot]=x%10,x/=10;// return dp(tot,0,0);for(int i=1;i<=19;i++) a[i]=0;a[20]=1;return dp(20,0,0); }inline __int128 read() {__int128 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 void write(__int128 x) {if(x<0){putchar('-');x=-x;}if(x>9)write(x/10);putchar(x%10+'0'); }int main() { // ios::sync_with_stdio(false); // cin.tie(0);memset(f,-1,sizeof(f));scanf("%lld",&mod);LL k=solve()%mod;write((__int128)mod-k+1); putchar(' ');write((__int128)100000000000000000*100+mod-k);puts("");return 0; } /**/總結
以上是生活随笔為你收集整理的Codeforces Round #268 (Div. 1) C. Hack it! 数位dp + 构造数位的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 吃什么中药能祛斑
- 下一篇: 补骨针打了有副作用吗