CCF 202112-3 登机牌条码
这算是本人第一次写(debug)出来大模拟的题。成就感max!
知识点:
vector的查询(下标),插入(insert),复制(assign)
queue的遍历输出(不能用for)
最重要的——求解多项式:
参考文章:(14条消息) CSP 202112-3 登机牌条码 (详细图解)_PolarDay.的博客-CSDN博客_机票条形码在线读取
一个多项式乘上xn,对应的结果就是向量向右移动n个位置,低位补0。{0,-3,1}
一个多项式乘上一个系数,对应的结果就是向量的各位同时乘上这个系数。{27,-9}
然后我们将这两个结果得到的向量相加最终得到{27,-12,1},对应的多项式为x2-12x+27,正是多项式运算的结果
求解多项式模板:
最重要的——多项式取模:
- 将除数乘上一个系数,使得被除数减除数之后能消掉最高位
- 被除数减除数
- 得到的结果继续按照第一步的方法计算,直到最终结果的最高位小于除数
多项式取模模板:
卡了半天的——取模问题
卡在80分的时候知道自己算法啥的没有错了,肯定是哪个地方数过大了。
曾思考是否每次取模这样的操作会对最终结果有影响? 答案是否定的!
当时卡在了计算3的k次方这个位置,看的出来当s = 8 时 k = 512,此时算出的结果有3512这么大,一定会爆的!
解决方法是自己写一个计算函数,并对每次结果取模。
long long Pow(int num,int index) { long long ans = 1; for(int i = 1; i <= index; i++) { ans *= num; ans %= 929; } return ans; }
还有,对于取模问题的进一步研究:
参考文章:(14条消息) 数论-取模问题总结_Kobe_G的博客-CSDN博客_对一个数取模
1.两数相加再取模
(m + n) % p = (m%p + n%p) %p
2.两数相乘再取模
(m * n) % p = (m%p) * (n%p) %p
3.两数相减再取模
(m - n) % p = ((m%p - n%p) + p) %p
对于上面的公式,在三个数及以上的时候也可以使用,用法因具体情况而异
AC代码:
#include<iostream> #include<string> #include<queue> #include<cmath> #include<vector> using namespace std; string str; queue<long long>q,ans; vector<long long>gx,gx_old,gx_new,dx; long long Pow(int num,int index) { long long ans = 1; for(int i = 1; i <= index; i++) { ans *= num; ans %= 929; } return ans; } void cal(int k) { int l = dx.size()-gx.size(); gx.insert(gx.begin(),l,0); int len = dx.size()-1; for(int i = len; i >= k ; i--) { int m = dx[i],leng = gx.size()-1; for(int j = i ; j >= 0 ; j--) { dx[j] -= gx[leng--] * m; dx[j] %= 929; } } for(int i = k-1 ; i >= 0; i-- ) { int n = -dx[i] % 929; if(n < 0) { n = 929 + n; } ans.push(n); } } void cal_gx(int k) { gx.insert(gx.begin(),1); gx.insert(gx.begin(),-3); for(int j = 2; j<=k; j++) { gx_old.assign(gx.begin(),gx.end()); gx.insert(gx.begin(),0); long long temp = -Pow(3,j); for(int i = 0 ; i< gx_old.size(); i++) { gx[i] += gx_old[i] * temp; gx[i] %= 929; } } } void cal_dx(int k) { int t = ans.size(); dx.insert(dx.begin(),ans.size()+1); while(t--) { dx.insert(dx.begin(),ans.front()); ans.push(ans.front()); ans.pop(); } while(k--) dx.insert(dx.begin(),0); } void print() { while(!ans.empty()) { //注意不能使用for遍历 cout << ans.front() << endl; ans.pop(); } } int main() { int w,s,k=0; cin >> w >> s; cin >> str; if(s != -1) k = pow(2,(s+1)); int flag = 0;//0 大写 1 小写 2 数字 for(int i = 0 ; i < str.size(); i++) { if(str[i] >= 'A' && str[i] <= 'Z' && flag == 0) { q.push(str[i]-'A'); } else if(str[i] >= 'a' && str[i] <= 'z' && flag == 1) { q.push(str[i]-'a'); } else if(str[i] >= '0' && str[i] <= '9' && flag == 2) { q.push(str[i]-'0'); } else { if(flag == 0 && str[i] >= 'a' && str[i] <= 'z') { q.push(27); flag = 1; } else if(flag == 0 && str[i] >= '0' && str[i] <= '9') { q.push(28); flag = 2; } else if(flag == 1 && str[i] >= 'A' && str[i] <= 'Z') { q.push(28); q.push(28); flag = 0; } else if(flag == 1 && str[i] >= '0' && str[i] <= '9') { q.push(28); flag = 2; } else if(flag == 2 && str[i] >= 'A' && str[i] <= 'Z') { q.push(28); flag = 0; } else if(flag == 2 && str[i] >= 'a' && str[i] <= 'z') { q.push(27); flag = 1; } i--; } } if(q.size()%2) q.push(29); while(!q.empty()) { int H = q.front(); q.pop(); int L = q.front(); q.pop(); ans.push(H*30+L); } if((ans.size()+1+k)%w != 0) { int temp = w-((ans.size()+1+k)%w); while(temp--) { ans.push(900); } } cout << ans.size()+1<< endl; cal_gx(k); cal_dx(k); cal(k); print(); }
本文作者:夏莱发电厂的Sensei
本文链接:https://www.cnblogs.com/Sensei/p/16472062.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步