CSP-202309-3-梯度求解

CSP-202309-3-梯度求解

  • 作為一個算法小白,本人第一次接觸大模擬的題,本題的算法參考自:【CSP】202309-3 梯度求解

解題思路

1.輸入處理

  • getchar();:從標準輸入讀取一個字符。這里它的作用可能是用來“吃掉”(消耗)前一個輸入后留下的換行符。確保getline能正確讀取到下一行文本。

  • getline(cin, op);:從標準輸入流cin中讀取一行文本,直到遇到換行符(用戶按下回車鍵),然后將讀取到的文本(不包括換行符)存儲到之前聲明的字符串變量中。

2.逐個處理表達式中的元素

(1)變量 x i x_i xi?的表示

struct elem {int index; // 變量索引,即x的下標long long value; // 變量值long long derivative; // 對應變量的導數值
};
  • 注意,這里因為最后求的是導函數的值,而無需記錄導數的形式。例如,對于 f ( x ) = x 2 , x = 1 f(x)=x^2,x=1 f(x)=x2,x=1,其導函數 f ′ ( x ) = 2 x f'(x)=2x f(x)=2x,這里我們直接記錄 f ′ ( 1 ) = 2 f'(1)=2 f(1)=2,即derivative=2

(2)將數字字符串轉換為長整型

long long str2ll(string a) {int sign = 1; // 判斷是正數還是負數long long ans = 0;if (a[0] == '-')sign = -1;for (int i = 0; i < a.length(); i++) {if (a[i] != '-')ans = 10 * ans + (a[i] - '0');}return ans * sign;
}

(3)使用 stringstream 逐個處理 op 字符串中的元素

  • std::stringstream 是一個流類,可以像輸入/輸出流一樣操作字符串。允許把字符串分割成多個部分,根據空白字符(如空格、制表符等)來拆分原始字符串。

  • 循環的作用是逐個讀取 op 字符串中的每個以空格分隔的子字符串,并在每次迭代中處理這些子字符串。這種處理方式對于解析和執行基于逆波蘭表示法(RPN)的算術表達式非常有效,因為它允許程序按照操作的順序(從左到右)逐步計算表達式的結果。

stringstream ss(op);
string s;
while (ss >> s) {}

(4)逆波蘭式的處理邏輯

  • 題目所給的字符串只涉及:x,x的索引,運算符+-*,常數
  • 整理來看可以分為兩類:變量+運算符,這也就明確了處理的邏輯。
    • 變量 x i x_i xi?,存入elem中。

      if (s[0] == 'x') {elem a;a.index = str2ll(s.substr(1, s.length() - 1)); // 得到變量下標a.derivative = xIndex == a.index ? 1 : 0; // 該變量是否要被求偏導(導數是 1,否則為 0)a.value = value[a.index]; // 變量在給定的值數組中的值st.push(a); // 將包含變量信息的結構體 a 壓入棧中,以便后續計算表達式的值和導數(和數字運算一樣)
      }
      
    • 運算符,由于求導運算本質上還是算數運算,并且是給定了變量值,本質上還是我們之前遇到過的算數運算的規則:遇到運算符,移出棧頂的兩個操作數,進行對應的運算res用于保存運算結果。

      elem op2 = st.top();
      st.pop();
      elem op1 = st.top();
      st.pop();
      elem res;
      
    • 由于求的是導數,這里的+-*不再是普通意義上的+-*,要符合導數運算的規則。

      switch (s[0]) {
      case '+': {res.value = ((op1.value + op2.value) % MOD + MOD) % MOD;res.derivative = ((op1.derivative + op2.derivative) % MOD + MOD) % MOD;break;
      }
      case '-': {res.value = ((op1.value - op2.value) % MOD + MOD) % MOD;res.derivative = ((op1.derivative - op2.derivative) % MOD + MOD) % MOD;break;
      }
      case '*': {res.value = ((op1.value * op2.value) % MOD + MOD) % MOD;res.derivative = ((op1.derivative * op2.value + op1.value * op2.derivative) % MOD + MOD) % MOD;
      }
      }
      st.push(res);
      
    • 常數,類似于非變量的 x i x_i xi?

      else {elem a;a.value = str2ll(s);a.derivative = 0;st.push(a);
      }
      
  • 最終,棧頂的結果即為運算結果。

3.完善代碼

#include <iostream>
#include <vector>
#include <stack>
#include <sstream>using namespace std;// 定義一個結構體 elem,用于表示表達式中的元素
struct elem {int index; // 變量索引long long value; // 變量值long long derivative; // 對應變量的導數
};const long long MOD = 1000000007; // 模數// 將字符串轉換為長整型
long long str2ll(string a) {int sign = 1; // 判斷是正數還是負數long long ans = 0;if (a[0] == '-')sign = -1;for (int i = 0; i < a.length(); i++) {if (a[i] != '-')ans = 10 * ans + (a[i] - '0');}return ans * sign;
}int main() {int n, m;cin >> n >> m; // 輸入變量個數和表達式數量string op;getchar();getline(cin, op); // 獲取表達式字符串vector<elem> expr;stack<elem> st;for (int i = 0; i < m; i++) {int xIndex;vector<long long> value(n + 1);cin >> xIndex; // 輸入變量xi,其余均視為常量for (int j = 1; j <= n; j++)cin >> value[j]; // 輸入每個變量的值stringstream ss(op);string s;while (ss >> s) {// 判斷是否是變量if (s[0] == 'x') {elem a;a.index = str2ll(s.substr(1, s.length() - 1)); // 得到變量的索引a.derivative = xIndex == a.index ? 1 : 0; // 變量對目標變量的導數是 1,否則為 0a.value = value[a.index]; // 變量在給定的值數組中的值st.push(a); // 將包含變量信息的結構體 a 壓入棧中,以便后續計算表達式的值和導數}// 檢查當前讀取到的字符串 s 是否只有一個字符且為加號、減號或乘號。如果是這三個運算符之一,就執行相應的運算邏輯else if (s.length() == 1 && (s[0] == '+' || s[0] == '-' || s[0] == '*')) {// 處理運算符的邏輯elem op2 = st.top();st.pop();elem op1 = st.top();st.pop();elem res;switch (s[0]) {case '+': {res.value = ((op1.value + op2.value) % MOD + MOD) % MOD;res.derivative = ((op1.derivative + op2.derivative) % MOD + MOD) % MOD;break;}case '-': {res.value = ((op1.value - op2.value) % MOD + MOD) % MOD;res.derivative = ((op1.derivative - op2.derivative) % MOD + MOD) % MOD;break;}case '*': {res.value = ((op1.value * op2.value) % MOD + MOD) % MOD;res.derivative = ((op1.derivative * op2.value + op1.value * op2.derivative) % MOD + MOD) % MOD;}}st.push(res);}else {elem a;a.value = str2ll(s);a.derivative = 0;st.push(a);}}long long ans = st.top().derivative;cout << ((ans % MOD) + MOD) % MOD << endl; // 輸出結果取模}return 0;
}

請添加圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/696107.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/696107.shtml
英文地址,請注明出處:http://en.pswp.cn/news/696107.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Kafka_04_Topic和日志

Kafka_04_Topic和日志 Topic/PartitionTopicPartition 日志存儲存儲格式日志清理刪除壓縮 Topic/Partition Topic/Partition: Kafka中消息管理的基礎單位 Topic和Partition并不實際存在(僅邏輯上的概念) 如: Topic和Partition關系 // 每個日志文件可對應多個日志分段, 其還可…

緩存篇—緩存擊穿

在很多場景下&#xff0c;我們的業務通常會有幾個數據會被頻繁地訪問&#xff0c;比如秒殺活動&#xff0c;這類被頻地訪問的數據被稱為熱點數據。 如果緩存中的某個熱點數據過期了&#xff0c;此時大量的請求訪問了該熱點數據&#xff0c;就無法從緩存中讀取&#xff0c;直接…

《UE5_C++多人TPS完整教程》學習筆記22 ——《P23 記錄加入的玩家(Couting Incoming Players)》

本文為B站系列教學視頻 《UE5_C多人TPS完整教程》 —— 《P23 記錄加入的玩家&#xff08;Couting Incoming Players&#xff09;》 的學習筆記&#xff0c;該系列教學視頻為 Udemy 課程 《Unreal Engine 5 C Multiplayer Shooter》 的中文字幕翻譯版&#xff0c;UP主&#xff…

前端面試問題(jwt/布局/vue數組下標/扁平化/菜單樹形/url api/新版本)

前端面試問題(jwt/布局/vue數組下標/扁平化/菜單樹形/url api/新版本) 1. jwt鑒權邏輯 前端 JWT 鑒權邏輯通常涉及在發起請求時攜帶 JWT&#xff0c;并在接收到響應后處理可能的授權問題。 1. 用戶登錄&#xff1a; 用戶提供憑證&#xff1a; 用戶在登錄界面輸入用戶名和密碼…

如何使用Docker部署MongoDB并結合內網穿透實現遠程訪問本地數據庫

文章目錄 前言1. 安裝Docker2. 使用Docker拉取MongoDB鏡像3. 創建并啟動MongoDB容器4. 本地連接測試5. 公網遠程訪問本地MongoDB容器5.1 內網穿透工具安裝5.2 創建遠程連接公網地址5.3 使用固定TCP地址遠程訪問 正文開始前給大家推薦個網站&#xff0c;前些天發現了一個巨牛的 …

2024最佳住宅代理IP服務商有哪些?

跨境出海已成為了近幾年的最熱趨勢&#xff0c;大批量的企業開始開拓海外市場&#xff0c;而海外電商領域則是最受歡迎的切入口。新興的tiktok、Temu&#xff0c;老牌的Amazon、Ebay&#xff0c;熱門的Etsy、Mecari等等都是藍海一片。跨境入門并不難&#xff0c;前期的準備中不…

深入理解文件查看命令:cat、more、less、tail、head

在Linux系統中&#xff0c;有許多命令用于查看文件的內容&#xff0c;其中包括cat、more、less、tail和head。這些命令提供了不同的方式來瀏覽文本文件&#xff0c;適用于各種查看需求。在本篇博客中&#xff0c;我們將深入介紹這些命令&#xff0c;并通過示例演示它們的用法。…

Spring Boot打war包部署到Tomcat,訪問頁面404 !!!

水善利萬物而不爭&#xff0c;處眾人之所惡&#xff0c;故幾于道&#x1f4a6; 文章目錄 Spring Boot打war包部署到Tomcat&#xff0c;訪問頁面404 &#xff01;&#xff01;&#xff01;解決辦法&#xff1a;檢查Tomcat版本和Jdk的對應關系&#xff0c;我的Tomcat是6.x&#x…

Sping基礎篇----掌握Sping的控制反轉/依賴注入的概念【實戰案例總結】

作為一名對技術充滿熱情的學習者&#xff0c;我一直以來都深刻地體會到知識的廣度和深度。在這個不斷演變的數字時代&#xff0c;我遠非專家&#xff0c;而是一位不斷追求進步的旅行者。通過這篇博客&#xff0c;我想分享我在某個領域的學習經驗&#xff0c;與大家共同探討、共…

SMMU介紹

SMMU&#xff08;System Memory Management Unit&#xff09;是一種硬件設備&#xff0c;其作用是在虛擬地址空間和物理地址空間之間提供地址轉換的功能。它通常用于處理虛擬化環境中的 I/O 設備&#xff0c;例如虛擬機中的設備訪問或者容器環境中的設備隔離。 SMMU 的主要作用…

KVM虛擬機的克隆方式

話不多說&#xff0c;直接上操作 首先確定我們要克隆的模板機器&#xff0c;這樣可以方便我們后續克隆許多機器 IP獲取最好就是dhcp模式&#xff0c;這樣克隆出來的機器就不需要自己再去改ip了 確定需要克隆的模板機以后&#xff0c;先關機再執行克隆操作 virsh shutdown ser…

【SiamFC】《Fully-Convolutional Siamese Networks for Object Tracking》

ECCV 2016 Workshops 文章目錄 1 Background and Motivation2 Related Work3 Advantages / Contributions4 Method5 Experiments5.1 Datasets and Metrics5.2 The OTB-13 benchmark5.3 The VOT benchmarks5.4 Dataset size 6 Conclusion&#xff08;own&#xff09;/ Future wo…

Android系統啟動流程

android的啟動流程是從底層開始進行的&#xff0c;具體如下所示&#xff1a; Android是基于Linux內核的系統&#xff0c;Android的啟動過程主要分為兩個階段&#xff0c;首先是Linux內核的啟動&#xff0c;然后是Android框架的啟動。 可以將Andorid系統的啟動流程分為以下五個…

【QT 5 +Linux下軟件桌面快捷方式+qt生成軟件創建桌面圖標+學習他人文章+第二篇:編寫桌面文件.desktop】

【QT 5 Linux下軟件桌面快捷方式qt生成軟件創建桌面圖標學習他人文章第二篇&#xff1a;編寫桌面文件.desktop】 1、前言2、實驗環境3、自我學習總結-本篇總結1、新手的疑問&#xff0c;做這件事目的2、了解.desktop3、三個關鍵目錄以及文件編寫1、目錄&#xff1a;/opt/2、目錄…

【鴻蒙 HarmonyOS 4.0】開發工具安裝

一、準備開發環境 1.1、安裝IDE 鴻蒙應用開發需要使用配套的IDE——HUAWEI DevEco Studio。 DevEco Studio基于IntelliJ IDEA Community&#xff08;IDEA社區版&#xff09;構建&#xff0c;為鴻蒙應用提供了一站式開發環境&#xff0c;集成了開發、運行、調試以及發布應用的…

【leetcode刷題之路】面試經典150題(3)——哈希表+區間

文章目錄 5 哈希表5.1 【哈希表】贖金信5.2 【數學】同構字符串5.3 【數學】單詞規律5.4 【哈希表】有效的字母異位詞5.5 【哈希表】字母異位詞分組5.6 【雙指針】兩數之和5.7 【數學】快樂數5.8 【哈希表】219. 存在重復元素 II5.9 【數學】最長連續序列 6 區間6.1 【數學】匯…

Stable Diffusion 模型分享:AstrAnime(Astr動畫)

本文收錄于《AI繪畫從入門到精通》專欄&#xff0c;專欄總目錄&#xff1a;點這里。 文章目錄 模型介紹生成案例案例一案例二案例三案例四案例五 下載地址 模型介紹 AstrAnime 是一個動漫模型&#xff0c;畫風色彩鮮明&#xff0c;擅長繪制漂亮的小姐姐。 條目內容類型大模型…

fastjson解析自定義get方法導致空指針問題

背景 為了在日志中把出入參打印出來&#xff0c;以便驗證鏈路和排查問題&#xff0c;在日志中將入參用fastjson格式化成字符串輸出&#xff0c;結果遇到了NPE。 問題復現 示例代碼 public static void main(String[] args) {OrganizationId orgId new OrganizationId();N…

規模化強化學習 — 多任務強化學習

1 簡述 1.1 單任務強化學習&#xff08;STRL&#xff09; 在單任務強化學習中&#xff0c;一個無人機的AI系統可能被訓練來執行特定的任務&#xff0c;比如自主導航。在這個任務中&#xff0c;無人機需要學習如何有效地從起點飛行到終點&#xff0c;并避開障礙物。 舉例&#…

【Java多線程】分析線程加鎖導致的死鎖問題以及解決方案

目錄 1、線程加鎖 2、死鎖問題的三種經典場景 2.1、一個線程一把鎖 2.2、兩個線程兩把鎖 2.3、N個線程M把鎖&#xff08;哲學家就餐問題&#xff09; 3、解決死鎖問題 1、線程加鎖 其中 locker 可以是任意對象&#xff0c;進入 synchronized 修飾的代碼塊, 相當于加鎖&…