http://www.elijahqi.win/archives/3435
题意翻译
现在存储了一个
2^a * 2^b
2a∗2b 的矩阵 • 矩阵在内存中是按行存储的 • 现在你想求它的转置 • 唯一允许的操作是交换两个内存位置的值 • 求最少需要的次数? • 4e5 组询问,每组询问 a + b <= 1e6
感谢@IceFox 提供的翻译
题目描述
输入输出格式
输入格式:
First line of input contains number of test cases c (1<=c<=400000). Each test case consists of two integers a,b (0<=a+b<=1000000).
输出格式:
For each test case output minimal number of swaps required to transpose an 2ax2b array. As it can be quite large, you have to output its remainder when divided by 1000003 (yes, it’s a prime number :).
输入输出样例
输入样例#1: 复制
3
1 1
2 2
5 7
输出样例#1: 复制
1
6
3744
观察到我们把这个内存的地址写下来其实是一些数左移了之后产生的数字
然后观察循环节个数 假如循环节个数是K 那么最后的交换次数就是2^(a+b)-k因为每个循环并不需要交换k次而是k-1次即可都交换完 考虑将原来假设为将a+b个珠子串成项链那么方案数怎么求
首先先看一个例子 假设a=3,b=6手动绘图
可以发现我们旋转之后最多转gcd(a,a+b)下 那么循环节长度即为(a+b)/(gcd(a,b))
考虑我们现在将什么重新标号了 这意味着 我们现在附近的点都会融合成一个点
这样得到一个新的项链
一共(a+b)/gcd(a,b)个珠子每个珠子都是可以用2^gcd(a,b) 填充
然后再接着化简公式即可 用常见的套路将Phi与预处理出来 每次只需要算出之后再*phi[i]&phi[n/i]即可
太困了 证明什么的可以看这位巨佬
https://blog.csdn.net/BraketBN/article/details/50668414
#include<cstdio>
#include<cctype>
#include<algorithm>
#define ll long long
using namespace std;
inline char gc(){
static char now[1<<16],*S,*T;
if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(!isdigit(ch)) {if (ch=='-') f=-1;ch=gc();}
while(isdigit(ch)) x=x*10+ch-'0',ch=gc();
return x*f;
}
const int mod=1000003;
const int N=1e6+10;
bool not_prime[N];
int bin[N],phi[N],prime[N],tot,n,g;
inline int gcd(int x,int y){return !y?x:gcd(y,x%y);}
inline int ksm(ll b,int t){static ll tmp;
for (tmp=1;t;b=b*b%mod,t>>=1) if (t&1) tmp=tmp*b%mod;return tmp;
}
inline void init(){
phi[1]=1;bin[0]=1;bin[1]=2;
for (int i=2;i<=1e6;++i){
bin[i]=bin[i-1]<<1;bin[i]%=mod;
if (!not_prime[i]) prime[++tot]=i,phi[i]=i-1;
for (int j=1;prime[j]*i<=1e6;++j){
not_prime[prime[j]*i]=1;
if (i%prime[j]==0){
phi[prime[j]*i]=phi[i]*prime[j];break;
}else phi[prime[j]*i]=phi[i]*phi[prime[j]];
}
}
}
inline int inc(int x,int v){return x+v>=mod?x+v-mod:x+v;}
inline int dec(int x,int v){return x-v<0?x-v+mod:x-v;}
inline int gao(){
int tmp=0;
for (int i=1;i*i<=n;++i){
if (n%i) continue;tmp=inc(tmp,(ll)phi[n/i]*bin[g*i]%mod);
if(i*i==n) continue;tmp=inc(tmp,(ll)phi[i]*bin[n/i*g]%mod);
}return (ll)tmp*ksm(n,mod-2)%mod;
}
int main(){
freopen("spoj422.in","r",stdin);
int T=read();init();
while(T--){
int a=read(),b=read();if (!a||!b) {puts("0");continue;}
g=gcd(a,a+b);n=(a+b)/g;
int ans=dec(bin[a+b],gao());printf("%d\n",ans);
}
return 0;
}