【NOI2018模拟4.2】table

Description:

这里写图片描述
这里写图片描述

题解:

做法1:

一行一行的看。

每次变换相当于乘上多项式(bx+a)。

所以可以搞出(bx+a)(p1)(bx+a)−(p−1)

乘第p行的数就可以还原出第一行,之后的用个组合数搞搞就行了。

(bx+a)(p1)(bx+a)−(p−1)的话,只用n项就可以了,并不用全部。

可以先把bx+a求逆,然后快速幂,O(n log^2 n)看上去有点悬。

也可以用二次项展开求出(bx+a)(p1)(bx+a)(p−1)先,再求逆,这个就只用O(n log n)O(n log n)

做法2:

x>=p很简单,要考虑x<<p怎么做。

重写一下方程,变成倒推的。

fi,j=(fi+1,jfi,j1b)/afi,j=(fi+1,j−fi,j−1∗b)/a
=fi+1,j/a+fi,j1(b/a)=fi+1,j/a+fi,j−1∗(−b/a)

这个可以再推一下方案数,类似于挡板问题。

Code:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define fo(i, x, y) for(int i = x; i <= y; i ++)
#define fd(i, x, y) for(int i = x; i >= y; i --)
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
using namespace std;

const int N = 1e7, M = 1e5, C = N + M;
const ll mo = 998244353;

int m, n, a, b, p, Q, x, y;
ll c[M + 5], d[M + 5], fac[C + 5], nif[C + 5], ans;
ll ca[C + 5], cb[M + 5], na[C + 5], nb[M + 5];
ll cc[M + 5];

ll ksm(ll x, ll y) {
    ll s = 1;
    for(; y; y /= 2, x = x * x % mo)
        if(y & 1) s = s * x % mo;
    return s;
}

ll Ci(ll a, ll b) { return fac[a] * nif[b] % mo * nif[a - b] % mo;}

int main() {
    freopen("table.in", "r", stdin);
    freopen("table.out", "w", stdout);
    fac[0] = 1; fo(i, 1, C) fac[i] = fac[i - 1] * i % mo;
    nif[0] = 1; nif[C] = ksm(fac[C], mo - 2);
    fd(i, C - 1, 1) nif[i] = nif[i + 1] * (i + 1) % mo;
    scanf("%d %d %d %d %d %d", &m, &n, &a, &b, &p, &Q);

    ca[0] = cb[0] = 1; ca[1] = a; cb[1] = b;
    na[0] = nb[0] = 1; na[1] = ksm(a, mo - 2); nb[1] = ksm(b, mo - 2);
    fo(i, 2, C) ca[i] = ca[i - 1] * ca[1] % mo, na[i] = na[i - 1] * na[1] % mo;
    fo(i, 2, M) cb[i] = cb[i - 1] * cb[1] % mo, nb[i] = nb[i - 1] * nb[1] % mo;
    cc[0] = 1; cc[1] = (ll) (mo - b) * ksm(a, mo - 2) % mo;
    fo(i, 2, M) cc[i] = cc[i - 1] * cc[1] % mo;

    fo(i, 1, n) scanf("%lld", &c[i]);

    for(; Q; Q --) {
        scanf("%d %d", &x, &y);
        if(x == p) {
            printf("%lld\n", c[y]);
        } else
        if(x < p) {
            int u = p - x;
            ans = 0;
            fo(i, 1, y) ans += c[i] * Ci(u + (y - i) - 1, u - 1) % mo * na[u] % mo * cc[y - i] % mo;
            printf("%lld\n", ans % mo);
        } else {
            int u = x - p;
            ans = 0;
            fo(i, max(1, y - u), y)
                ans += c[i] * Ci(u, y - i)  % mo * cb[y - i] % mo * ca[u - (y - i)] % mo;
            printf("%lld\n", ans % mo);
        }
    }

}
% 步骤1: 读取数据 filename = 'D:/data4.xlsx'; data = readtable(filename, 'VariableNamingRule', 'preserve'); % 步骤2: 科学加权方法 - 熵权法确定权重 % 熵权法是一种客观赋权法,根据数据本身的离散程度确定权重 medals = data.NOI_Medals; prizes = data.NOIP_Prizes; % 标准化数据 medals_norm = (medals - min(medals)) / (max(medals) - min(medals)); prizes_norm = (prizes - min(prizes)) / (max(prizes) - min(prizes)); % 计算信息熵 p_medals = medals_norm / sum(medals_norm); p_prizes = prizes_norm / sum(prizes_norm); % 避免log(0)错误 p_medals(p_medals == 0) = eps; p_prizes(p_prizes == 0) = eps; e_medals = -sum(p_medals .* log(p_medals)) / log(length(medals)); e_prizes = -sum(p_prizes .* log(p_prizes)) / log(length(prizes)); % 计算差异系数和权重 d_medals = 1 - e_medals; d_prizes = 1 - e_prizes; w_NOI = d_medals / (d_medals + d_prizes); w_NOIP = d_prizes / (d_medals + d_prizes); fprintf('熵权法确定的权重: NOI=%.4f, NOIP=%.4f\n', w_NOI, w_NOIP); % 计算综合得分 score = w_NOI * medals + w_NOIP * prizes; data.Score = score; % 步骤3: 按学校分组计算平均综合得分 [schoolGroups, schoolIDs] = findgroups(data.School); schoolScores = splitapply(@nanmean, data.Score, schoolGroups); schoolNames = unique(data.School); % 创建学校得分表 schoolResults = table(schoolNames, schoolScores, 'VariableNames', {'School', 'AvgScore'}); schoolResults = sortrows(schoolResults, 'AvgScore', 'descend'); % 步骤4: 多种可视化展示 % 4.1 学校得分排名条形图 (前20名) figure('Position', [100, 100, 800, 600]); subplot(2,2,1); topN = min(20, height(schoolResults)); barh(schoolResults.AvgScore(1:topN), 'FaceColor', [0.2, 0.6, 0.8]); set(gca, 'YTick', 1:topN, 'YTickLabel', schoolResults.School(1:topN)); title('学校综合得分排名 (前20名)'); xlabel('平均综合得分'); grid on; axis tight; % 4.2 所有学校得分分布 subplot(2,2,2); histogram(schoolResults.AvgScore, 30, 'FaceColor', [0.8, 0.4, 0.2]); title('学校综合得分分布'); xlabel('综合得分'); ylabel('学校数量'); grid on; % 4.3 随时间变化的综合得分热力图 subplot(2,2,3); % 创建学校-年份得分矩阵 years = unique(data.Year); scoreMatrix = nan(length(schoolNames), length(years)); for i = 1:length(schoolNames) schoolData = data(strcmp(data.School, schoolNames{i}), :); [~, yearIdx] = ismember(schoolData.Year, years); scoreMatrix(i, yearIdx) = schoolData.Score; end % 按平均得分排序 [~, sortIdx] = sort(schoolScores, 'descend'); sortedScoreMatrix = scoreMatrix(sortIdx(1:min(30, end)), :); % 显示前30名 imagesc(sortedScoreMatrix); colorbar; set(gca, 'XTick', 1:length(years), 'XTickLabel', string(years)); set(gca, 'YTick', 1:size(sortedScoreMatrix,1), 'YTickLabel', schoolNames(sortIdx(1:size(sortedScoreMatrix,1)))); title('学校综合得分随时间变化 (前30名)'); xlabel('年份'); ylabel('学校'); colormap(jet); % 4.4 地理分布气泡图 (需要地理坐标数据,此处为示例) % 假设有省份数据 subplot(2,2,4); if ismember('Province', data.Properties.VariableNames) provinceGroups = findgroups(data.Province); provinceScores = splitapply(@nanmean, data.Score, provinceGroups); provinceNames = unique(data.Province); % 创建模拟坐标 (实际应用中应使用真实坐标) rng(42); % 固定随机种子 lon = rand(length(provinceNames), 1) * 30 + 100; % 模拟经度 lat = rand(length(provinceNames), 1) * 20 + 20; % 模拟纬度 % 气泡大小基于得分 bubbleSize = 100 + provinceScores * 50; geobubble(lat, lon, bubbleSize, provinceNames); title('各省份综合得分分布'); geolimits([15 45], [100 130]); % 中国大致范围 else text(0.5, 0.5, '无省份数据', 'HorizontalAlignment', 'center'); axis off; title('省份分布数据缺失'); end 对缺失数据线性插值,进一步优化算法
07-22
% 步骤1: 读取数据并计算综合得分 filename = 'D:/data4.xlsx'; data = readtable(filename, 'VariableNamingRule', 'preserve'); w_NOI = 0.7; % NOI权重 w_NOIP = 0.3; % NOIP权重 score = w_NOI * data.NOI_Medals + w_NOIP * data.NOIP_Prizes; data.Score = score; % 步骤2: 按中学分组并处理缺失值 schools = unique(data.School); nSchools = numel(schools); results = table('Size', [nSchools, 4], 'VariableTypes', {'string', 'double', 'double', 'double'}, ... 'VariableNames', {'School', 'Slope', 'Intercept', 'RSquared'}); for i = 1:nSchools schoolName = schools{i}; idx = strcmp(data.School, schoolName); schoolData = data(idx, :); years = schoolData.Year; scores = schoolData.Score; % 按年份排序 [years_sorted, sortIdx] = sort(years); scores_sorted = scores(sortIdx); % 线性插值处理缺失值 (核心修改) nanIdx = isnan(scores_sorted); if any(nanIdx) validIdx = find(~nanIdx); if numel(validIdx) >= 2 scores_sorted(nanIdx) = interp1(validIdx, scores_sorted(validIdx), find(nanIdx), 'linear', 'extrap'); end end % 检查有效数据点 validScores = scores_sorted(~isnan(scores_sorted)); validYears = years_sorted(~isnan(scores_sorted)); if numel(validYears) < 2 results.School(i) = schoolName; results.Slope(i) = NaN; results.Intercept(i) = NaN; results.RSquared(i) = NaN; continue; end % 归一化年份 yearsNorm = validYears - min(validYears); % 拟合线性模型 X = [ones(size(yearsNorm)), yearsNorm]; [b, ~, ~, ~, stats] = regress(validScores, X); % 存储结果 (修正了截距存储错误) results.School(i) = schoolName; results.Slope(i) = b(2); results.Intercept(i) = b(1); % 修正:存储截距b(1)而非斜率 results.RSquared(i) = stats(1); end % 步骤3: 分析整体趋势 validIdx = ~isnan(results.Slope); meanSlope = mean(results.Slope(validIdx)); fprintf('所有中学竞赛水平的平均年增长率: %.4f\n', meanSlope); % 步骤4: 可视化 - 斜率分布直方图 figure; histogram(results.Slope(validIdx), 'BinWidth', 0.5); title('参赛中学竞赛水平年增长率分布'); xlabel('斜率 (\beta_i)'); ylabel('中学数量'); grid on; % 步骤5: 可视化 - 标注学校名称 (核心新增) figure; hold on; scatter(1:numel(validIdx), results.Slope(validIdx), 30, 'filled'); text(1:numel(validIdx), results.Slope(validIdx), results.School(validIdx),... 'FontSize',8, 'HorizontalAlignment','right', 'VerticalAlignment','middle'); title('各中学竞赛水平增长率'); xlabel('学校索引'); ylabel('增长率 (斜率)'); grid on; hold off; 采取科学的加权方法 可视化展示中学的综合得分
最新发布
07-22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值