codevs1376帕秋莉•诺蕾姬 东方幻想乡系列模拟赛Stage 2[三星]
2015-10-24 13:00
323 查看
题目很老但是很经典~
题目链接:—————————————->题目地址
能被 M 整除
.
.
.
.
.
这题看完题目很容易想出来n^2*l复杂度的算法,即,枚举两端点,每次暴力求sum,然后暴力验证取模,这样复杂度是n^2*l。这是30分算法。
然后对于剩下的50,m<= 26;乱搞一下~,不过不如直接打100分算法。
对于100分算法,我们这样想,26进制向10进制转换,也就是将第i位的数乘上26^(i-1),于是我们可以先处理出来一个num数组,保存的是每一位的数(如ABC,num[1] = 0,num[2] = 1,num[3] = 2)这样的,这里还要特别注意,这是一个类似高精的读入,也就是第一个读入的是最高位……
然后我们再处理一个v数组,表示v是第i位需要乘的数(可以不处理,但是打起来比较麻烦不如直接预处理一下,并且还不用打快速幂),递推关系式:
并且这里要注意的是,这里处理的v是在%m意义下的,因为完整的v数组存不下来,又有取模的性质,所以可以直接在这里取模,而且,为了保险还是要每步都取模。
这时候,对初始序列处理sum,到这里都和暴力算法没什么区别,但是,下面的枚举过程暴力是对于每一次交换都暴力求和,这里可不可以优化一下呢?
既然每次只交换两个数,那么这两个数对答案造成影响,而其他数不会,那么我们可以理解成:先把这两位掏空,然后再填上两个新的数。
于是就有转移:sum-num[i] * v[j]-num[j] * v[j] + num[i] * v[j] + num[j] * v[i];即
这个过程就是掏空重填的过程。
然后每次交换后检查一下是否满足%m == 0,如果满足就加到新的数组里,这是因为要求字典序最小,当然你也可以从小到大枚举。
最后,输出最小值,不满足就-1 -1~
暴力还是很容易想的~,后面的思路也不是很难,但是有一定思维难度~多思考~思维的乐趣~
全部代码:
题目链接:—————————————->题目地址
题目描述 Description
在幻想乡,帕秋莉•诺蕾姬是以宅在图书馆闻名的魔法使。这一天帕秋莉又在考虑如何加强魔法咒语的威力。帕秋莉的魔法咒语是一个仅有大写字母组成的字符串,我们考虑从’A’到’Z’分别表示0到25的数字,于是这个魔法咒语就可以看作一个26进制数。帕秋莉通过研究发现,如果一个魔法咒语所代表的数能够整除10进制数M的话,就能够发挥最大的威力。若当前的魔法咒语并不能整除M,帕秋莉只会将其中两个字符的位置交换,尽量让它能够被M整除,当然由于某些咒语比较特殊,无论怎么改变都不能达到这个目的。请你计算出她能否只交换两个字符就让当前咒语被M整除。(首位的’A’为前导0) 第1行:1个字符串,长度不超过L。 第2行:1个正整数,M 第1行:用空格隔开的2个整数,输出时先输位置靠前的那个。 如果存在多种交换方法,输出字典序最小的,比如1 3和1 5都可以达到目的,就输出1 3;1 3和2 4都行时也输出1 3。注意字符串下标从左到右依次为1到L开始。如果初始魔法咒语已经能够整除M,输出”0 0”;若无论如何也不能到达目的输出”-1 -1”。 PATCHOULI 16 4 9 对于30%的数据:1 <= L <= 10, 1 <= M <= 100 对于50%的数据:除前面30%外,1 <= L <= 500, M = 5或25或26 对于100%的数据:1 <= L <= 2,000, 1 <= M <= 200,000输入描述 Input Description
第1行:1个字符串,长度不超过L。 第2行:1个正整数,M输出描述 Output Description
第1行:用空格隔开的2个整数,输出时先输位置靠前的那个。 如果存在多种交换方法,输出字典序最小的,比如1 3和1 5都可以达到目的,就输出1 3;1 3和2 4都行时也输出1 3。注意字符串下标从左到右依次为1到L开始。如果初始魔法咒语已经能够整除M,输出”00”;若无论如何也不能到达目的输出”-1-1”。样例输入 Sample Input
PATCHOULI 16样例输出 Sample Output
4 9数据范围及提示 Data Size & Hint
对于30%的数据:1 <= L <= 10, 1 <= M <= 100 对于50%的数据:除前面30%外,1 <= L <= 500, M = 5或25或26 对于100%的数据:1 <= L <= 2,000, 1 <= M <= 200,000这题的简要题目描述:
对于给定的字符串,转化为 26 进制数字,交换其中两个字母的位置,使得这个数字能被 M 整除
.
.
.
.
.
题解
(接下来的’^’符号一定是次方运算不是异或)这题看完题目很容易想出来n^2*l复杂度的算法,即,枚举两端点,每次暴力求sum,然后暴力验证取模,这样复杂度是n^2*l。这是30分算法。
然后对于剩下的50,m<= 26;乱搞一下~,不过不如直接打100分算法。
对于100分算法,我们这样想,26进制向10进制转换,也就是将第i位的数乘上26^(i-1),于是我们可以先处理出来一个num数组,保存的是每一位的数(如ABC,num[1] = 0,num[2] = 1,num[3] = 2)这样的,这里还要特别注意,这是一个类似高精的读入,也就是第一个读入的是最高位……
然后我们再处理一个v数组,表示v是第i位需要乘的数(可以不处理,但是打起来比较麻烦不如直接预处理一下,并且还不用打快速幂),递推关系式:
[code] v[1] = 1%m; v[2] = pr%m; for(int i = 3;i <= 2300;i ++) { v[i] = (v[i-1]%m * pr%m)%m; }
并且这里要注意的是,这里处理的v是在%m意义下的,因为完整的v数组存不下来,又有取模的性质,所以可以直接在这里取模,而且,为了保险还是要每步都取模。
这时候,对初始序列处理sum,到这里都和暴力算法没什么区别,但是,下面的枚举过程暴力是对于每一次交换都暴力求和,这里可不可以优化一下呢?
既然每次只交换两个数,那么这两个数对答案造成影响,而其他数不会,那么我们可以理解成:先把这两位掏空,然后再填上两个新的数。
于是就有转移:sum-num[i] * v[j]-num[j] * v[j] + num[i] * v[j] + num[j] * v[i];即
[code] for(int i = 1;i <= l;i ++) { for(int j = 1;j <= l;j ++) { if(i == j) continue; sum = sum - num[i]*v[i] - num[j]*v[j] + num[i]*v[j] + num[j]*v[i]; } }
这个过程就是掏空重填的过程。
然后每次交换后检查一下是否满足%m == 0,如果满足就加到新的数组里,这是因为要求字典序最小,当然你也可以从小到大枚举。
最后,输出最小值,不满足就-1 -1~
暴力还是很容易想的~,后面的思路也不是很难,但是有一定思维难度~多思考~思维的乐趣~
全部代码:
[code]#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; typedef long long ll; const int size = 2333; char s[size]; ll m; int num[size]; ll v[size]; ll sum; int tot; struct Poi{int l,r;}pre[size]; bool cmp(Poi a,Poi b) { return a.l == b.l ? a.r < b.r : a.l < b.l; } int main() { ll pr = (ll)(26); scanf("%s%lld",s+1,&m); int l = strlen(s+1); for(int i = l;i > 0;i --) { num[l-i+1] = s[i]-'A'; } v[1] = 1%m; v[2] = pr%m; for(int i = 3;i <= 2300;i ++) { v[i] = (v[i-1]%m * pr%m)%m; } for(int i = 1;i <= l;i ++) { sum += (ll)(num[i])*v[i]; } if(sum % m == 0) { puts("0 0"); return 0; } ll tmp = sum; for(int i = 1;i <= l;i ++) { for(int j = 1;j <= l;j ++) { if(i == j) continue; sum = sum - num[i]*v[i] - num[j]*v[j] + num[i]*v[j] + num[j]*v[i]; if(sum % m == 0) { int p = i,q = j; if(p < q) swap(p,q); p = l - p + 1; q = l - q + 1; pre[++tot].l = p; pre[tot].r = q; } sum = tmp; } } if(tot) { sort(pre+1,pre+1+tot,cmp); printf("%d %d",pre[1].l,pre[1].r); return 0; } puts("-1 -1"); return 0; }
相关文章推荐
- Hbase结构简单、作法
- 九度OJ 1150:Counterfeit Dollar(假美元) (分析、检验)
- 地图定位
- Android属性动画完全解析(二)
- uoj #139. 【UER #4】被删除的黑白树 dfs序 贪心
- 对于sizeof的含义、应用及易混点的解析
- hibernate HQL new xxx() 查询 join连接多个表,并把连接后的表保存到一个新类中
- android----Timer和TimerTask的使用
- Apache Mesos【一】Apache Mesos的整体架构
- android-----用代码安装apk文件
- 图片上传到服务器
- 二叉树的建立方法总结
- ios多线程开发总结
- 九度OJ 1149:子串计算 (计数、排序)
- 九度OJ 1149:子串计算 (计数、排序)
- 【Virtualbox】开启虚拟化
- 写让别人能读懂的代码
- thinkst 视频搜索网站
- 九度OJ 1148:Financial Management(财务管理) (平均数)
- #define M(row,col) m[col*4+row]宏定义代码全解