题面玄乎冗长,故事倒是挺好。 题解简单明了,尽显高深玄妙。 代码格式清晰,就是注释太少。 今天题目可订?你怕是在说笑!
#include<bits/stdc++.h> #define ll long long using namespace std; const int N = 5e5+5; char p[N]; int ans=0, lenp; inline char Cc(int a) {return char(a+'0');} inline int Ci(char a) {return a-'0';}//char和int的转换 int main() { scanf("%s", p+1); lenp = strlen(p+1); //输入 for(int i = 1; i <= lenp; i++) ans += Ci(p[i]); ans = 9-(ans%9); printf("%d\n", ans); //求删去的那个数 p[++lenp] = Cc(ans); ans = 0; for(int i = 1; i <= lenp; i++) { ans = ans*10+Ci(p[i]); p[i] = Cc(ans/9); ans %= 9; } //求x for(int i = 1; i <= lenp; i++) printf("%d", Ci(p[i])); puts("0"); //输出10x即s printf("0"); for(int i = 1; i <= lenp; i++) printf("%d", Ci(p[i])); //输出x即t return 0; }
#include <cstdio> #define ll long long; using namespace std; const ll mod = 1e9+7; const int N = 2e7+10; ll M(ll a){return a%mod;} int n, M; ll f[31][2], fac[N], inv[N], ans; ll pow(ll x,ll y){ ll c = 1; while(y){ if(y & 1) c = M( c*x ); b >>= 1; x = M( x*x ); } return c; } void prep() { fac[0] = 1; for(int i = 1; i <= n; i++) fac[i] = M( fac[i-1]*i ); inv[n] = pow(fac[n], mod-2); for(int i = n-1; i >= 1; i--) inv[i] = M( inv[i+1]*(i+1) ); }//处理阶乘及逆元 ll dfs(int left, int x, int y) { //left表示剩下的,还需要填多少数 ll tmpf[31][2]; for(int i = 0; i <= M; i++) for(int j = 0; j <= 1; j++) tmpf[i][j] = f[i][j]; ll tot = 0;//计算n中质因数数量至少x个的数 的数量 for(int i = x; i <= M; i++) for(int j = y; j <= 1; j++) tot += f[i][j], f[i][j] = 0; if (!x && !y){ for(int i = 0; i <= M; i++) for(int j = 0; j <= 1; j++) f[i][j] = tmpf[i][j]; return fac[tot]; }//边界 ll ans = 0; if (x) ans += dfs(left-tot, x-1, y);//gcd/2的情况 if (y) ans += dfs(left-tot, x, y-1);//gcd/3的情况 for(int i = 0; i <= M; i++) for(int j = 0; j <= 1; j++) f[i][j] = tmpf[i][j]; return M( M( fac[left-1]*inv[left-tot] ) * M( tot*ans ) ); //处理gcd不变的情况 //fac[left-1]*inv[left-tot] //等式转换一下,就是从left-tot+1乘到left-1,有tot个数填进去满足这个条件,就可以填1个,2个,3个…… } int main(){ scanf("%d", &n); prep(); f[0][0] = n; for(M = 1; f[M - 1][0]; M++) f[M][0] = f[M-1][0]>>1; M -= 2; //n可以分解出M+1个2 for(int i = 0; i <= M; i++) f[i][0] -= f[i+1][0];//减去重复,至少转换为恰好有 //(f[i][0]原先计算的是至少有i个2的数,减一减变成,恰好有i个2的数) f[0][1] = n / 3;//n中有0个2,1个3的数 for(int i = 1; i <= M-1; i++) f[i][1] = f[i-1][1]>>1; //n中有i个2,1个3的数,是n中有i-1个2,1个3的数除以2 for(int i = 0; i <= M-1; i++) f[i][1] -= f[i+1][1];//减去重复,至少转换为恰好有 for(int i = 0; i <= M; i++) f[i][0] -= f[i][1]; //n中有i个2,0个3的数 要减去 n中有i个2,1个3的数 ans = dfs(n, M, 0);//2^(M)的方案数 if (3*(1<<(M-1)) <= n) ans += dfs(n, M-1, 1); //如果2^(M)能够转换为另一种形式2^(M-1)*3,那么还要加上另外的方案数 printf("%lld\n", M(ans)); return 0; }