杭电第五场补题
1001 Tetrahedron(A)
思路:
本题意在求四面体直角顶点到底面的距离的平方的倒数的1/h^2值的期望值;三直角边的长度分别为a, b, c 则可计算得1/h^2 = 1/a^2 + 1/b^2 + 1/c^2; 由于对于a, b, c, 此三者都为等概率出现,因而有 原式 = 3 * 1/a^2; 那么1/h^2的期望值则为3 * [Σ1, (1/n^2) ]/ n % mod; 在写代码时,只需先用一个数组将所有的3 * [Σ1, (1/n^2) ], (n = 1, 2, 3……)存起来然后按照算式输出答案即。
代码:
#include <bits/stdc++.h>
#include <vector>
using namespace std;
typedef long long ll;
const ll maxn = 6e6 + 20;
const ll mod = 998244353;
ll ksm(ll a, ll b){
ll ans = 1;
while(b){
if(b&1) ans = (ans * a) % mod;
a = (a * a) % mod;
b >>= 1;
}
return ans;
}
ll dp[maxn];
void init(){//1--i的平方倒数的和
ll ans = 0;
for(ll i = 1; i <= 6000001; i++){
ll x = ((i * i) % mod);
ans = (ans + (ksm(x, mod - 2) % mod));
dp[i] = (ans * 3) % mod;
}
}
int main (){
init();
ll t; scanf("%lld", &t);
while(t--){
ll n; scanf("%lld", &n);
printf("%lld\n", dp[n] * ksm(n, mod - 2) % mod);//3*(1/Σ1,(i^2))/n%mod;
}
return 0;
}
1003 Boring Game
思路:
在翻折的过程中,数字是以一小块一小块的形式移动的,数字块数据的多少又是根据对折次数的增加而减少的,因此只需要记录每个数据的翻折之后的位置和数字块的位置再对应输出即可。
代码:
#include <bits/stdc++.h>
#include <vector>
using namespace std;
typedef long long ll;
const int N = 5e5 + 5;
const int mod = 998244353;
int n, m, k;
int jc[20];
int in[N];//内部数据位置
int ans[N];
vector<int> block;//外部翻折分块情况。
void solve(){
scanf("%d%d", &n, &k);
int total = 2 * n * jc[k];
for(int i = 1; i <= total; i++) in[i] = i;
int len = total / 2;
block.clear();
block.push_back(1);
for(int i = 1; i <= k; i++){
for(int j = 1; j <= total; j += len*2) reverse(in+j, in+len+j);
len /= 2;
}
for(int i = 1; i <= k; i++){
for(int j = 0; j < block.size(); j++) block[j] *= 2;
for(int j = block.size()-1; j >= 0; j--) block.push_back(block[j]-1);
}
reverse(block.begin(), block.end());
for(int i = 1; i <= total; i++){
int x; scanf("%d", &x);
ans[i] = x;
}
len *= 2;
for(int i = 1; i <= n*2; i++){
for(int j = 1; j <= jc[k]; j++){
printf("%d", ans[in[i + len*(block[j-1]-1)]]);
if(i != n*2 || j != jc[k]) printf(" ");
}
}
printf("\n");
}
int main(){
int T; scanf("%d", &T);
jc[0] = 1;
for(int i = 1; i <= 15; i++) jc[i] = jc[i-1] * 2;
while(T--) solve();
return 0;
}
1009 Paperfolding
思路:
假设只进行水平对折x次,则剪下纸片的数量为 2 * ( 2^x + 1);仅进行竖直对折亦是如此,当水平对折和垂直对折同时进行是时,剪下纸片的数量变为:代入x或y其一为0,仍然满足。
所以由此可得纸片的数量期望为:
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
int T; ll n;
ll ksm(ll x, ll k) {
ll ret = 1;
for (; k; k>>=1, x = x * x % mod) if(k & 1) ret = ret * x % mod;
return ret;
}
int main() {
scanf("%d", &T);
while (T--) {
scanf("%lld", &n);
ll ans = 1 + ksm(2, n);
ll t=3ll * ksm(2, mod-2) % mod;
(ans = ans + 2 * ksm(t, n) % mod) %= mod;
printf("%lld\n",ans);
}
return 0;
}