题意:

给出a、b 表示按先行后列的方式储存矩阵 现在要将其转置 可以交换两个点的位置 求最小操作次数

题解:

储存可以将其视为拉成一条链 设a=5、b=2 则在链上坐标用2^***(a,b)表示为(xxxxxyy) 转置后为(yyxxxxx)

这时将其视为另一个点的坐标 继续转置为(xxyyxxx)... 直到再变成(xxxxxyy)这样每次循环可以节省1次转置 所以ans=2^(a+b)-k k为循环的个数
k的计算:右移b位 右移b*2位 右移b*3位... 构成了一个置换群 置换个数为(a+b)/***(a,b)

因为它是循环的 所以向右移bx位 可视为右移bx%(a+b)位 设bx=z(mod (a+b))

该方程有解条件为***(b,(a+b))|z -> ***(a,b)|z 所以z为***(a,b)的倍数

k的值可理解为将长度为(a+b)/***(a,b)的串 染成2^***(a,b)种颜色(循环移动视为同种方案) 的方案数

既为poj2154的题目

因为spoj会卡常数 这题很容易TLE 我做了几个优化:

1.记忆化欧拉函数 将算过的欧拉函数存下来 下次直接用

2.预处理幂 可以发现这题要用的幂都是2^x 可以直接预处理出来

3.dfs n的因数 枚举m的因数会浪费很多时间 可以先算出n的质因数 在通过dfs算出其因数

4.尽量不要用long long 在会超int的地方强制转换一下就行

这题时限是8s 我跑了4.2s 目测前面T了十几次

代码:

 #include <cstdio>
#define _(x) static_cast<long long>(x)
const int mo=;
typedef int ll;
ll t,a,b,n,m,g,phii[],primer[],np,flag[],pow[],ans,p[],nn;
void makep(ll t){
for (int i=;i<=np && t> && primer[i]*primer[i]<=t;i++)
if (t%primer[i]==){
p[++nn]=primer[i];
while (t%primer[i]==) t/=primer[i];
}
if (t>) p[++nn]=t;
}
ll phi(ll t){
ll out=,tt=t;
if (phii[t]) return phii[t];
for (int i=;i<=np && t> && primer[i]*primer[i]<=t;i++)
if (t%primer[i]==){
t/=primer[i];
out=_(out)*_((primer[i]-))%mo;
while (t%primer[i]==) t/=primer[i],out=_(out)*_(primer[i])%mo;
}
if (t>) out=_(out)*_((t-))%mo;
return phii[tt]=out;
}
void dfs(ll now,ll sum){
if (now>nn){
ans=(ans+_(phi(n/sum))*_(pow[sum*g]))%mo;
return;
}
for (ll i=;n%i==;i*=p[now]) dfs(now+,sum*i);
}
void extgcd(ll a,ll b,ll &x,ll &y){
if (!b) x=,y=;
else{
extgcd(b,a%b,x,y);
ll t=x;
x=y;
y=t-a/b*y;
}
}
ll gcd(ll a,ll b){
while (b) b^=a^=b^=a%=b;
return a;
}
ll work(){
if (!a || !b) return ;
ll x,y;
g=gcd(a,b);
n=(a+b)/g;
nn=ans=;
makep(n);
dfs(,);
extgcd(n,mo,x,y);
x=(x%mo+mo)%mo;
ans=(_(ans)*_(x))%mo;
return ((pow[a+b]-ans)%mo+mo)%mo;
}
void makepr(){
for (int i=;i<=;i++){
if (!flag[i]) primer[++np]=i;
for (int j=;j<=np && primer[j]*i<=;j++){
flag[primer[j]*i]=;
if (i%primer[j]==) break;
}
}
pow[]=;
for (int i=;i<=;i++) pow[i]=(pow[i-]*)%mo;
}
int main(){
freopen("spoj442.in","r",stdin);
freopen("spoj442.out","w",stdout);
scanf("%d\n",&t);
makepr();
while (t--){
if (t==){
t=;
}
scanf("%d%d\n",&a,&b);
printf("%d\n",work());
}
fclose(stdin);
fclose(stdout);
}

【SPOJ】Transposing is even more fun!的更多相关文章

  1. 【SPOJ】NUMOFPAL - Number of Palindromes(Manacher,回文树)

    [SPOJ]NUMOFPAL - Number of Palindromes(Manacher,回文树) 题面 洛谷 求一个串中包含几个回文串 题解 Manacher傻逼题 只是用回文树写写而已.. ...

  2. 【SPOJ】Substrings(后缀自动机)

    [SPOJ]Substrings(后缀自动机) 题面 Vjudge 题意:给定一个长度为\(len\)的串,求出长度为1~len的子串中,出现最多的出现了多少次 题解 出现次数很好处理,就是\(rig ...

  3. 【SPOJ】Longest Common Substring II (后缀自动机)

    [SPOJ]Longest Common Substring II (后缀自动机) 题面 Vjudge 题意:求若干个串的最长公共子串 题解 对于某一个串构建\(SAM\) 每个串依次进行匹配 同时记 ...

  4. 【SPOJ】Longest Common Substring(后缀自动机)

    [SPOJ]Longest Common Substring(后缀自动机) 题面 Vjudge 题意:求两个串的最长公共子串 题解 \(SA\)的做法很简单 不再赘述 对于一个串构建\(SAM\) 另 ...

  5. 【SPOJ】Distinct Substrings(后缀自动机)

    [SPOJ]Distinct Substrings(后缀自动机) 题面 Vjudge 题意:求一个串的不同子串的数量 题解 对于这个串构建后缀自动机之后 我们知道每个串出现的次数就是\(right/e ...

  6. 【SPOJ】Distinct Substrings/New Distinct Substrings(后缀数组)

    [SPOJ]Distinct Substrings/New Distinct Substrings(后缀数组) 题面 Vjudge1 Vjudge2 题解 要求的是串的不同的子串个数 两道一模一样的题 ...

  7. 【SPOJ】Power Modulo Inverted(拓展BSGS)

    [SPOJ]Power Modulo Inverted(拓展BSGS) 题面 洛谷 求最小的\(y\) 满足 \[k\equiv x^y(mod\ z)\] 题解 拓展\(BSGS\)模板题 #inc ...

  8. 【SPOJ419】Transposing is Fun Pólya定理+欧拉函数

    [SPOJ419]Transposing is Fun 题意:给你一个$2^a\times2^b$的矩阵,将$1...n$中的数依次从左到右,从上往下填到矩阵里,再把矩阵转置,然后把所有数从左到右,从 ...

  9. 【SPOJ】QTREE7(Link-Cut Tree)

    [SPOJ]QTREE7(Link-Cut Tree) 题面 洛谷 Vjudge 题解 和QTREE6的本质是一样的:维护同色联通块 那么,QTREE6同理,对于两种颜色分别维护一棵\(LCT\) 每 ...

随机推荐

  1. The type sun.management.ManagementFactory is not visible

    Eclipse默认将这些受访问限制的API设成了Error.解决方法:只要将Windows---Preferences---Java--Complicer---Errors/Warings里面的Dep ...

  2. sqort函数用法总结

    qsort包含在<stdlib.h>头文件中,此函数根据你给的比较条件进行快速排序,通过指针移动实现排序.排序之后的结果仍然放在原数组中.使用qsort函数必须自己写一个比较函数. 函数原 ...

  3. (六)CSS伪元素

    CSS伪元素用于向某些选择器设置特殊效果. 伪元素的用法和伪类相似: selector:pseudo-element {property:value;} CSS类也可以与伪元素配合使用: select ...

  4. java导出excel报表

    1.java导出excel报表: package cn.jcenterhome.util; import java.io.OutputStream;import java.util.List;impo ...

  5. MySQL学习笔记一

    MySQL 学习笔记 一 一.数据库简单介绍 1. 按照数据库的发展时间顺序,主要出现了以下类型数据库系统: Ø 网状型数据库 Ø 层次型数据库 Ø 关系型数据库 Ø 面向对象数据库 上面4中数据库系 ...

  6. poj 3468 A Simple Problem with Integers (线段树 成段更新 加值 求和)

    题目链接 题意: 只有这两种操作 C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.&quo ...

  7. Fragment 和 FragmentActivity的使用(二)

      今天继续完成剩下的学习部分,现在项目很多地方使用viewpager来提供滑动,今天记录学习viewpager配合fragment的显示,增加一个CallLogsFragment配合之前SMSLis ...

  8. ArrayList和List之间的转换

    开发中不免碰到List与数组类型之间的相互转换,举一个简单的例子: package test.test1; import java.util.ArrayList; import java.util.L ...

  9. UVa 11174 (乘法逆元) Stand in a Line

    题意: 有n个人排队,要求每个人不能排在自己父亲的前面(如果有的话),求所有的排队方案数模1e9+7的值. 分析: <训练指南>上分析得挺清楚的,把公式贴一下吧: 设f(i)为以i为根节点 ...

  10. bzoj1863: [Zjoi2006]trouble 皇帝的烦恼

    白书原题.l边界又设错啦.一般都是错这里吧.注意为什么这里不能是l=0.(只是为了判断第一个和最后一个 #include<cstdio> #include<cstring> # ...