题解 黑客(续)
作者:互联网
相对简单的数位DP,需要高精
- 需要注意的是类似数位DP这样的DP用记搜实现状态数可能会比刷表少很多
- 对于类似「为啥
1<<2
等于1啊」这样的问题,康康你存的类型是不是int,尤其注意是不是开成bool了
于是令 \(dp[i][j]\) 为由低位到高位考虑到第 \(i\) 位,当前不能再选的数的集合为 \(s\) 时的方案数
一开始定义时由高向低,已经选的数集合为 \(s\),但不方便记搜
转移枚举当前还能选的数转移
Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 510
#define ll long long
#define pb push_back
#define int128 __int128
#define int long long
#define ull unsigned long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
char sta[N]; int top;
inline void write(int128 t) {
top=0;
do {sta[++top]=char('0'+t%10); t/=10;} while (t);
while (top) putchar(sta[top--]);
printf("\n");
}
const ull base=1000000000;
struct bigint{
ull a[120]; int siz;
bigint(){siz=1; memset(a, 0, sizeof(a));}
bigint(ll t){siz=1; memset(a, 0, sizeof(a)); *this=t;}
inline ull& operator [] (int t) {return a[t];}
void put() {printf("%lld", a[siz]); for (int i=siz-1; i>0; --i) printf("%09lld", a[i]); printf("\n");}
inline void operator = (ll t) {
siz=0;
do {
++siz;
a[siz]=t%base;
t/=base;
} while (t) ;
}
inline bigint operator * (bigint b) {
bigint ans;
// cout<<siz<<' '<<b.siz<<endl;
// exit(0);
for (int i=1; i<=siz; ++i) {
for (int j=1; j<=b.siz; ++j) {
// cout<<"ij: "<<i<<' '<<j<<endl;
// exit(0);
ans[i+j-1]+=a[i]*b[j];
ans[i+j]+=ans[i+j-1]/base;
ans.siz=max(ans.siz, i+j-1);
if (ans[i+j-1]/base) ans.siz=max(ans.siz, i+j);
ans[i+j-1]%=base;
}
}
// exit(0);
for (int i=1; i<=ans.siz; ++i) {
ans[i+1]+=ans[i]/base;
if (ans[i]/base) ans.siz=max(ans.siz, i+1);
ans[i]%=base;
}
return ans;
}
inline bigint operator * (ll t) {
bigint ans; ans=t;
ans=ans*(*this);
return ans;
}
inline bigint operator + (bigint b) {
bigint ans;
int lim=max(siz, b.siz);
for (int i=1; i<=lim; ++i) {
ans[i]+=a[i]+b[i];
ans[i+1]+=ans[i]/base;
ans.siz=max(ans.siz, i);
if (ans[i]/base) ans.siz=max(ans.siz, i+1);
ans[i]%=base;
}
return ans;
}
inline bigint operator + (ll t) {
bigint ans; ans=t;
ans=ans+(*this);
return ans;
}
inline bool operator ! () {return siz<=1&&a[1]==0;}
};
inline bigint qpow(bigint a, int b) {bigint ans; ans=1ll; for (; b; a=a*a,b>>=1) if (b&1) ans=ans*a; return ans;}
int n, m, k;
vector<int> ban[N];
namespace force{
int s[N];
int128 ans1, ans2;
void check() {
ll tem=0;
for (int i=1; i<=n; ++i) tem=(tem<<3)+(tem<<1)+s[i];
++ans1; ans2+=tem;
}
void dfs(int u) {
if (u>n) {check(); return ;}
for (int i=1; i<=k; ++i) {
for (auto it:ban[i]) for (int j=1; j<u; ++j) if (it==s[j]) goto jump;
s[u]=i;
dfs(u+1);
jump: ;
}
}
void solve() {
dfs(1);
// printf("%lld\n%lld\n", ans1, ans2);
write(ans1); write(ans2);
exit(0);
}
}
namespace task1{
inline int128 qpow(int128 a, int b) {int128 ans=1; for (; b; a=a*a,b>>=1) if (b&1) ans=ans*a; return ans;}
void solve() {
write(qpow(k, n));
int128 ans=0, tem=qpow(k, n-1), lst=k*(k+1)/2;
for (int i=1; i<=n; ++i) {
ans=ans+tem*lst;
lst*=10;
}
write(ans);
exit(0);
}
}
namespace task2{
void solve() {
bigint k2; k2=1ll*k;
bigint tem=qpow(k2, n); tem.put();
bigint ans, lst; ans=0, lst=0;
tem=qpow(k2, n-1);
// tem=tem*tem;
for (int i=1; i<=k; ++i) lst=lst+i;
for (int i=1; i<=n; ++i) {
// cout<<"i: "<<i<<endl;
ans=ans+tem*lst;
lst=lst*10;
}
ans.put();
exit(0);
}
}
namespace task{
int tot, disable[10];
bigint f[510][1<<9], g[510][1<<9], ans, p[510], tem;
bool able[1<<9][10], vis[510][1<<9];
void dfs(int u, int s) {
if (vis[u][s]) return ;
if (u>n) {f[u][s]=1; g[u][s]=0; vis[u][s]=1; return ;}
for (int i=0; i<k; ++i) if (!(s&(1<<i))) {
int v=u+1, t=s|disable[i];
dfs(v, t);
f[u][s]=f[u][s]+f[v][t];
g[u][s]=g[u][s]+g[v][t]*10+f[v][t]*(i+1);
}
vis[u][s]=1;
}
void solve() {
// cout<<double(sizeof(f)*2)/1024/1024<<endl;
#if 0
for (int i=0; i<n; ++i) {
for (int s=0; s<lim; ++s) if (!(!f[i][s])) {
for (int j=0; j<k; ++j) if (able[s][j]) {
f[i+1][s|(1<<j)]=f[i+1][s|(1<<j)]+f[i][s];
}
}
}
for (int s=0; s<lim; ++s) ans=ans+f[n][s];
ans.put();
p[0]=1;
for (int i=1; i<=n; ++i) p[i]=p[i-1]*10;
for (int i=0; i<k; ++i) g[1][1<<i]=p[n-1]*(i+1);
for (int i=1; i<n; ++i) {
// cout<<"i: "<<i<<endl;
for (int s=0; s<lim; ++s) if (!(!g[i][s])) {
tem=p[n-i-1]*f[i][s];
for (int j=0; j<k; ++j) if (able[s][j]) {
g[i+1][s|(1<<j)]=g[i+1][s|(1<<j)]+g[i][s]+tem*(j+1);
++tot;
}
}
}
ans=0;
for (int s=0; s<lim; ++s) ans=ans+g[n][s];
ans.put();
#else
for (int i=0; i<k; ++i) for (auto it:ban[i+1]) disable[i]|=1<<(it-1);
dfs(1, 0);
f[1][0].put(); g[1][0].put();
// cout<<f[1][0]<<' '<<g[1][0]<<endl;
#endif
// cout<<"tot: "<<tot<<endl;
}
}
signed main()
{
freopen("hacker2.in", "r", stdin);
freopen("hacker2.out", "w", stdout);
n=read(); m=read(); k=read();
for (int i=1,a,b; i<=m; ++i) {
a=read(); b=read();
ban[b].pb(a);
}
// force::solve();
// task1::solve();
// if (!m) task2::solve();
// else force::solve();
task::solve();
return 0;
}
标签:return,int,题解,long,黑客,ans,int128,define 来源: https://www.cnblogs.com/narration/p/15369211.html