题目背景
本题中出现的神犇:_lgswdn
AK 完 NOI 后,lgd 一路势不可挡,不久便进入了国家队,来到了 IOI 赛场。
题目描述
6ms 后,lgd 写对了最后一题的
可持久化非确定状态AC自动分块维护线段平衡仙人掌优化最小费用最大流预处理混合图上莫比乌斯反演莫队带花舞蹈链并查集树状数组套主席树预处理动态DP分治FFT求多项式逆元对数函数的指数函数用可持久化并查集合并最小费用循环流上插头DP
算法,AK 了 IOI。于是他闲着无聊,开始给自己出题。
有一题是这样的:
nn 个同学站成一个圆圈,其中的一个同学手里拿着一个球。每一次,手里有球的同学可以把球传给自己左右的两个同学中的一个(左右任意)。那么有多少种不同的传球方法可以使得从 lgd 手里开始传的球,传了 mm 次以后,又回到 lgd 自己手里呢?两种传球方法被视作不同的方法,当且仅当这两种方法中,接到球的同学按接球顺序组成的序列是不同的。
你听说这道题之后,希望把它做出来,以不遭到 lgd 的鄙视。由于 lgd 比较仁慈,他允许你只告诉他答案取模 720000054000001720000054000001 的余数就好了。
输入格式
此题有多组数据。
对于每组数据,一行两个正整数 n,mn,m,含义如题。
输出格式
对于每组数据,一行一个自然数表示答案。
输入输出样例
输入 #1复制
5 7 5 5 5 4 5 5 5 9
输出 #1复制
14 2 6 2 72
输入 #2复制
100000 998684 100000 998671 100000 998110
输出 #2复制
513030267786335 0 570065615362699
说明/提示
本题采用捆绑测试。
本题有多组数据。
请注意常数因子带来的程序效率及空间占用上的影响。
数据范围如下表所示。
数据点编号 | nn | mm | 数据组数 | 分值 | 特殊性质 | 子任务编号 |
---|---|---|---|---|---|---|
1\sim61∼6 | =100=100 | \le100≤100 | \le5≤5 | 55 | A | 0 |
7\sim127∼12 | =10^5=105 | \le10^6≤106 | \le5≤5 | 1515 | A | 1 |
13\sim1813∼18 | =10^6=106 | \le2\times10^6≤2×106 | \le5≤5 | 1010 | A | 2 |
19\sim2419∼24 | =2\times10^5=2×105 | \le10^{1000}≤101000 | \le5≤5 | 2020 | A | 3 |
25\sim3025∼30 | \le6\times10^6≤6×106 | \le10^{30}≤1030 | \le50≤50 | 2020 | 4 | |
31\sim3631∼36 | \le6\times10^6≤6×106 | \le10^{10^4}≤10104 | \le2500≤2500 | 3030 | 5 |
特殊性质 A:所有输入的 nn 全部相同。
对于 100\%100% 的数据,n\
#include<bits/stdc++.h>
#define ll unsigned long long
#define int unsigned int
#define N 30000003
#define P 720000054000001
#define i128 __int128_t
using namespace std;
const int pr[2] = {24000001,30000001};
const int g[2] = {23,14};
int ifac[N],sw[503][9][8];
int p,inv1k;
inline int power(int a,int t,int m){
int res = 1;
while(t){
if(t&1) res = (ll)res*a%m;
a = (ll)a*a%m;
t >>= 1;
}
return res;
}
void init(int id){
inv1k = power(1000,p-2,p);
ifac[0] = 1,ifac[p-1] = p-1;
for(int i=p-2;i;--i) ifac[i] = (ll)ifac[i+1]*(i+1)%p;
int r = power(g[id],(p-1)/1000,p),w = 1,iw = 1;
int ir = power(r,p-2,p);
for(int i=0;i<500;++i){
sw[i][0][0] = 1,sw[i][0][1] = w+iw;
for(int k=2;k<8;++k) sw[i][0][k] = (ll)sw[i][0][k-1]*sw[i][0][1]%p;
for(int j=1;j<9;++j){
sw[i][j][0] = 1,sw[i][j][1] = (ll)sw[i][j-1][7]*sw[i][j-1][1]%p;
for(int k=2;k<8;++k) sw[i][j][k] = (ll)sw[i][j][k-1]*sw[i][j][1]%p;
}
w = (ll)w*r%p,iw = (ll)iw*ir%p;
}
}
inline void multiply(const int *f,const int *g,int n,int *r){
static int h[28];
memset(h,0,sizeof(h));
for(int i=0;i<n;++i)
for(int j=0;j<n;++j)
h[i+j] = (h[i+j]+(ll)f[i]*g[j])%p;
for(int i=0;i<n;++i) r[i] = (h[i]+h[i+n])%p;
}
inline int solve(int n,ll m,int rt){
int pw,t;
ll res = 0;
if(n==13){
static int f[28],g[28];
memset(f,0,sizeof(f));
memset(g,0,sizeof(g));
f[1] = f[n-1] = g[0] = 1;
while(1){
if(m&1) multiply(f,g,n,g);
m >>= 1;
if(m==0) break;
multiply(f,f,n,f);
}
return g[0];
}
if(m&1) return 0;
if(n==1000){
for(int i=0;i<500;++i){
pw = 1,t = m;
for(int j=0;t;++j){
if(t&7) pw = (ll)pw*sw[i][j][t&7]%p;
t >>= 3;
}
res += pw;
}
return (res<<1)%p*inv1k%p;
}
if(n<=100){
int r = power(rt,(p-1)/n,p);
int ir = power(r,p-2,p),w = 1,iw = 1;
n >>= 1;
for(int i=0;i<n;++i){
res += power(w+iw,m,p);
w = (ll)w*r%p,iw = (ll)iw*ir%p;
}
return (res<<1)%p*power(n<<1,p-2,p)%p;
}
int st = (m>>1)%(n>>1),len = n>>1;
for(int k=st;(k<<1)<m;k+=len) res += (ll)ifac[k]*ifac[m-k]%p;
return ((res<<1)+(ll)ifac[m>>1]*ifac[m>>1])%p*power(ifac[m],p-2,p)%p;
}
inline ll crt(int x,int y){
return ((i128)x*pr[1]*power(pr[1],pr[0]-2,pr[0])+(i128)y*pr[0]*power(pr[0],pr[1]-2,pr[1]))%P;
}
struct query{
int n,m0,m1,x,y;
ll m13;
inline query(int _n=0,int _m0=0,int _m1=0,int _x=0,int _y=0):n(_n),m0(_m0),m1(_m1),x(_x),y(_y){}
}a[2503];
char str[10003];
int m0,m1,x,y,l,cnt;
ll m13;
signed main(){
int n;
p = pr[0];
init(0);
while(scanf("%d%s",&n,str)==2){
l = strlen(str);
m1 = m0 = m13 = 0;
for(int i=0;i<l;++i) m0 = (m0*10+str[i]-'0')%(pr[0]-1);
if(n==13){
for(int i=0;i<l;++i)
m13 = (m13*10+str[i]-'0')%((ll)pr[1]*pr[1]-1);
}else{
for(int i=0;i<l;++i)
m1 = (m1*10+str[i]-'0')%(pr[1]-1);
}
x = solve(n,m0,g[0]);
a[++cnt] = (query(n,m0,m1,x));
a[cnt].m13 = m13;
}
p = pr[1];
init(1);
for(int i=1;i<=cnt;++i){
x = a[i].x;
y = solve(a[i].n,a[i].n==13?a[i].m13:a[i].m1,g[1]);
printf("%lld\n",crt(x,y));
}
return 0;
}