2020杭電多校第六場題解
阿新 • • 發佈:2020-08-07
2020 Multi-University Training Contest 6
施工中。。。
1001 Road To The 3rd Building
求得每個數的機率,得到相應的差分公式,然後求兩次差分即可。
#include<bits/stdc++.h> #define ll long long #define maxn 400010 #define mod 1000000007 using namespace std; ll poow(ll x,ll y){ ll bas=1; while(y){ if(y%2) bas=bas*x%mod; x=x*x%mod; y/=2; } return bas; } ll po(ll x){ return poow(x,mod-2); } ll inv[maxn],ans[maxn],a[maxn]; int main(){ inv[0]=1; for(int i=1;i<200010;i++) inv[i]=po(i); int t; scanf("%d",&t); while(t--){ int n; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%lld",&a[i]),ans[i]=0; for(int i=1;i<=n/2;i++){ ans[1]+=inv[i]; ans[i+1]-=inv[i]; ans[n+2-i]-=inv[i]; ans[1]+=inv[n+1-i]; ans[i+1]-=inv[n+1-i]; ans[n+2-i]-=inv[n+1-i]; ans[1]%=mod; ans[i+1]%=mod; ans[n+2-i]%=mod; } if(n%2){ ans[1]+=inv[(n+1)/2]; ans[1]%=mod; ans[(n+1)/2+1]-=2*inv[(n+1)/2]; ans[(n+1)/2+1]%=mod; } for(int i=2;i<=n;i++) ans[i]=(ans[i-1]+ans[i])%mod; for(int i=2;i<=n;i++) ans[i]=(ans[i-1]+ans[i])%mod; ll sum=0; for(int i=1;i<=n;i++) sum=(sum+ans[i]*a[i]%mod)%mod; while(sum<0) sum+=mod; sum=sum*inv[n]%mod*inv[n+1]%mod*2%mod; printf("%lld\n",sum); } return 0; }
1002 Little Rabbit's Equation
純粹模擬,切忌輸出1(WA的教訓)。
#include<bits/stdc++.h> #define ll long long #define maxn 200010 #define mod 998244353 using namespace std; char a[200]; int main(){ map<char,int>mp; for(int i=0;i<10;i++){ mp['0'+i]=i; } for(int i=0;i<6;i++){ mp['A'+i]=10+i; } while(scanf("%s",a)!=EOF){ int n=strlen(a); vector<int>s1,s2,s3; int cnt=0,ma=1; while(cnt<n){ if(!mp.count(a[cnt])) break; s1.push_back(mp[a[cnt]]); ma=max(ma,mp[a[cnt]]); cnt++; } char pe=a[cnt++]; while(cnt<n){ if(!mp.count(a[cnt])) break; s2.push_back(mp[a[cnt]]); ma=max(ma,mp[a[cnt]]); cnt++; } cnt++; while(cnt<n){ if(!mp.count(a[cnt])) break; s3.push_back(mp[a[cnt]]); ma=max(ma,mp[a[cnt]]); cnt++; } int ans=-1; for(int i=ma+1;i<=16&&ans==-1;i++){ __int128 x=0,y=0,z=0; for(int j=0;j<s1.size();j++){ x=x*i+s1[j]; } for(int j=0;j<s2.size();j++){ y=y*i+s2[j]; } for(int j=0;j<s3.size();j++){ z=z*i+s3[j]; } if(pe=='+'){ if(x+y==z) ans=i; } else if(pe=='-'){ if(x-y==z) ans=i; } else if(pe=='*'){ if(x*y==z) ans=i; } else if(pe=='/'){ if(y*z==x) ans=i; } } printf("%d\n",ans); } return 0; }
1003 Borrow
dp+概率+組合數,還有注意某些情況有重複計算。
博主補完題後神志不清,暫時無法解釋原理。
#include<bits/stdc++.h> #define ll long long #define maxn 1000010 #define mod 998244353 using namespace std; ll dp[maxn][2]; ll fac[maxn],inv[maxn],in2[maxn]; ll po(ll x){ ll bas=1,y=mod-2; while(y){ if(y%2) bas=bas*x%mod; x=x*x%mod; y/=2; } return bas; } ll C(int n,int m){ return fac[n]*inv[m]%mod*inv[n-m]%mod; } int main(){ fac[0]=inv[0]=1; for(int i=1;i<maxn;i++){ fac[i]=fac[i-1]*i%mod; } inv[maxn-1]=po(fac[maxn-1]); for(int i=maxn-2;i>=1;i--){ inv[i]=inv[i+1]*(i+1)%mod; } dp[0][0]=0; ll p2=po(2); in2[0]=1; for(int i=1;i<maxn;i++){ in2[i]=in2[i-1]*p2%mod; } for(int i=1;i<maxn;i++){ dp[i][0]=2+dp[i-1][1]; dp[i][1]=2+dp[i-2][0]; } int t; scanf("%d",&t); while(t--){ int x,y,z; scanf("%d%d%d",&x,&y,&z); if((x+y+z)%3){ printf("-1\n"); continue; } if(x>y) swap(x,y); if(y>z) swap(y,z); if(x>y) swap(x,y); x=z-x,y=z-y; if(y==0||y==1){ printf("%lld\n",dp[x][y]); continue; } ll ans=0; for(int i=x;i>=2;i--){ if((x-i+y-1)%3==0&&(x-i+y-1)/3<=x-i&&(x-i+y-1)/3<=y-1){ ll sum=(x-i+y-1)/3; ll num=x-i-sum; ans=(ans+(sum+dp[i][1])%mod*C(sum,num)%mod*in2[sum]%mod)%mod; } else if((x-i+y)%3==0&&(x-i+y)/3<=x-i&&(x-i+y)/3<=y){ ll sum=(x-i+y)/3; ll num=x-i-sum; ll cu=C(sum,num); if(num!=0) cu-=C(sum-1,num-1); ans=(ans+(cu*in2[sum]%mod)*(sum+dp[i][0])%mod)%mod; } } for(int i=y;i>=2;i--){ if((y-i+x-1)%3==0&&(y-i+x-1)/3<=y-i&&(y-i+x-1)/3<=x-1){ ll sum=(x-i+y-1)/3; ll num=y-i-sum; ans=(ans+C(sum,num)*(sum+dp[i][1])%mod*in2[sum]%mod)%mod; } else if((x-i+y)%3==0&&(x-i+y)/3<=y-i&&(x-i+y)/3<=x){ ll sum=(x-i+y)/3; ll num=y-i-sum; ll cu=C(sum,num); if(num!=0) cu-=C(sum-1,num-1); ans=(ans+(cu*in2[sum]%mod)*(sum+dp[i][0])%mod)%mod; } } while(ans<0) ans+=mod; printf("%lld\n",ans); } return 0; }
1005 Fragrant numbers
賽時打表跑數小時,喜提WA。
賽後補題,區間DP,跑得飛快。
題目需要注意的無非就是一個區間中能組合出哪些數。
#include<bits/stdc++.h>
#define ll long long
#define maxn 400010
#define mod 1000000007
using namespace std;
int a[10]={1,1,4,5,1,4,1,9,1,9};
int pe[20][20][100010];
int dp[5010];
int sol(int l,int r){
int sum=0;
for(int i=l;i<=r;i++){
sum=sum*10+a[(i-1)%10];
}
return sum;
}
int main(){
memset(dp,-1,sizeof(dp));
for(int i=1;i<=13;i++){
pe[i][i][a[(i-1)%10]]=1;
}
for(int len=1;len<13;len++){
for(int i=1;i+len<=13;i++){
int j=i+len;
if(len<4){
int x=sol(i,j);
if(x<=5000) pe[i][j][x]=1;
}
for(int mid=i;mid<j;mid++){
for(int k=1;k<=5000;k++){
if(pe[i][mid][k]==0) continue;
for(int u=1;u<=5000;u++){
if(pe[mid+1][j][u]==0) continue;
if(k+u<=5000) pe[i][j][k+u]=1;
if(k*u<=5000) pe[i][j][k*u]=1;
}
}
}
}
}
for(int i=13;i>=1;i--){
for(int j=1;j<=5000;j++){
if(pe[1][i][j]) dp[j]=i;
}
}
int t;
scanf("%d",&t);
while(t--){
int x;
scanf("%d",&x);
printf("%d\n",dp[x]);
}
return 0;
}
1006 Paperfolding
#include <bits/stdc++.h>
#pragma warning (disable:4996)
using namespace std;
typedef long long LL;
const int maxn = 1e5 + 5;
const LL mod = 1e9 + 7;
struct Line {
int u, v;
LL w;
}line[maxn * 2];
int f[maxn];
int find(int x) {
while (x != f[x])
x = f[x] = f[f[x]];
return x;
}
typedef pair<int, LL>pii;
vector<pii> E[maxn];
int a[maxn];
LL n_size[maxn][2], sum[maxn][2];
int main() {
int t;
scanf("%d", &t);
while (t--) {
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
int u, v;
LL w = 1;
for (int i = 1; i <= m; i++) {
scanf("%d%d", &line[i].u, &line[i].v);
w = w * 2 % mod;
line[i].w = w;
}
int limit = n;
for (int i = 1; i <= n; i++) {
f[i] = i;
E[i].clear();
}
for (int i = 1; i <= m; i++) {
int eu = find(line[i].u);
int ev = find(line[i].v);
if (eu != ev) {
f[eu] = ev;
E[line[i].u].push_back(make_pair(line[i].v, line[i].w));
E[line[i].v].push_back(make_pair(line[i].u, line[i].w));
limit--;
if (limit == 1)
break;
}
}
LL ans = 0;
function<void(int, int)> dfs;
dfs = [&](int now, int fa) {
n_size[now][0] = n_size[now][1] = 0;
sum[now][0] = sum[now][1] = 0;
n_size[now][a[now]] = 1;
for (auto it : E[now]) {
if (it.first == fa)
continue;
dfs(it.first, now);
n_size[now][0] += n_size[it.first][0];
sum[now][0] = (sum[now][0] + sum[it.first][0] + n_size[it.first][0] * it.second % mod) % mod;
n_size[now][1] += n_size[it.first][1];
sum[now][1] = (sum[now][1] + sum[it.first][1] + n_size[it.first][1] * it.second % mod) % mod;
}
for (auto it : E[now]) {
if (it.first == fa)
continue;
ans=(ans+(sum[it.first][0] + n_size[it.first][0] * it.second %mod)%mod*(n_size[now][1] - n_size[it.first][1])%mod
+(sum[it.first][1] + n_size[it.first][1] * it.second %mod)%mod*(n_size[now][0] - n_size[it.first][0])%mod)%mod;
}
};
dfs(1, 0);
printf("%lld\n", ans);
}
return 0;
}
1009 Divisibility
#include <bits/stdc++.h>
#pragma warning (disable:4996)
using namespace std;
int main() {
int t;
scanf("%d", &t);
while (t--) {
long long b, x;
scanf("%lld%lld", &b, &x);
if (b <= x) printf("F\n");
else if (b % x == 1) printf("T\n");
else printf("F\n");
}
return 0;
}
1010 Expectation
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e4 + 5;
const LL mod = 998244353;
struct Line {
int u, v;
LL w;
} line[maxn];
LL quickpow(LL m, LL p) {
LL res = 1;
while (p) {
if (p & 1)
res = res * m % mod;
m = m * m % mod;
p >>= 1;
}
return res;
}
namespace Matrix {
const int maxn = 105;
LL a[maxn][maxn];
LL ans;
void work(int n) {
for (int i = 2, inv, tmp; i <= n; ++i) {
for (int j = i + 1; j <= n; ++j)
if (!a[i][i] && a[j][i]) {
ans = -ans;
swap(a[i], a[j]);
break;
}
inv = quickpow(a[i][i], mod - 2);
for (int j = i + 1; j <= n; ++j) {
tmp = (LL)a[j][i] * inv % mod;
for (int k = i; k <= n; ++k)
a[j][k] = (a[j][k] - (LL)a[i][k] * tmp % mod) % mod;
}
}
}
LL slove(int n, int m, LL limit) {
ans = 1;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
a[i][j] = 0;
for (int i = 1; i <= m; ++i) {
if (!(line[i].w & limit))
continue;
int x = line[i].u, y = line[i].v;
a[x][x]++;
a[y][y]++;
a[x][y]--;
a[y][x]--;
}
work(n);
for (int i = 2; i <= n; ++i)
ans = (LL)ans * a[i][i] % mod;
return (ans % mod + mod) % mod;
}
} // namespace Matrix
int main() {
int t;
scanf("%d", &t);
while (t--) {
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++)
scanf("%d%d%lld", &line[i].u, &line[i].v, &line[i].w);
LL ans = 0;
for (int i = 0; i <= 31; i++)
ans = (ans + (1 << i) % mod * Matrix::slove(n, m, (1 << i)) % mod) %
mod;
LL inv = Matrix::slove(n, m, (LL(1) << 32) - 1);
inv = quickpow(inv, mod - 2);
ans = ans * inv % mod;
printf("%lld\n", ans);
}
return 0;
}