真尼玛刺激啊 T了几次 然后感觉要把欧拉函数预处理出来 QAQ
改一下就过了 用map标记了 (数据1e9)
欧拉降幂水题 CF难度分2700
#include<stdlib.h>
#include<algorithm>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<map>
#include<time.h>
#include <cstdio>
#include <iostream>
#include <vector>
#define ll long long
#define inf 0x3f3f3f3f
#define mods 1000000007
#define modd 998244353
#define PI acos(-1)
#define fi first
#define se second
#define lowbit(x) (x&(-x))
#define mp make_pair
#define pb push_back
#define si size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
#define IOS ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
ll gcd(ll a,ll b){if(a<0)a=-a;if(b<0)b=-b;return b==0?a:gcd(b,a%b);}
template<typename T>void read(T &res){bool flag=false;char ch;while(!isdigit(ch=getchar()))(ch=='-')&&(flag=true);
for(res=ch-48;isdigit(ch=getchar());res=(res<<1)+(res<<3)+ch - 48);flag&&(res=-res);}
ll lcm(ll a,ll b){return a*b/gcd(a,b);}
ll qqpp(ll a,ll b,ll m)
{
ll res=1;
while(b>0)
{
if(b&1) {res=res*a;if(res>=m) res=res%m+m;}
a=a*a;if(a>=m) a=a%m+m;
b>>=1;
}
return res;
}
ll qp(ll a,ll b,ll mod){ll ans=1;if(b==0){return ans%mod;}while(b){if(b%2==1){b--;ans=ans*a%mod;}a=a*a%mod;b=b/2;}return ans%mod;}//快速幂%
ll qpn(ll a,ll b, ll p){ll ans = 1;a%=p;while(b){if(b&1){ans = (ans*a)%p;--b;}a =(a*a)%p;b >>= 1;}return ans%p;}//逆元 (分子*qp(分母,mod-2,mod))%mod;
ll pow_mod(ll x,ll n,ll mod){ll res=1;while(n){if(n&1)res=res*x%mod;x=x*x%mod;n>>=1;}return res;}
ll fact_pow(ll n,ll p){ll res=0;while(n){n/=p;res+=n;}return res;}
ll mult(ll a,ll b,ll p)
{
a%=p;
b%=p;
ll r=0,v=a;
while(b)
{
if(b&1)
{
r=(r+v)%p;
r=(r+p)%p;
}
v<<=1;
v=(v+p)%p;
b>>=1;
}
return r%p;
}
ll quick_pow(ll a,ll b,ll p){ll r=1,v=a%p;while(b){if(b&1)r=mult(r,v,p);v=mult(v,v,p);b>>=1;}return r;}
bool CH(ll a,ll n,ll x,ll t)
{ll r=quick_pow(a,x,n);ll z=r;for(ll i=1;i<=t;i++){r=mult(r,r,n);if(r==1&&z!=1&&z!=n-1)return true;z=r;}return r!=1;}
bool Miller_Rabin(ll n)
{if(n<2)return false;if(n==2)return true;if(!(n&1))return false;ll x=n-1,t=0;while(!(x&1)){x>>=1;t++;}
srand(time(NULL));ll o=8;for(ll i=0;i<o;i++){ll a=rand()%(n-1)+1;if(CH(a,n,x,t))return false;}return true;}
ll exgcd(ll a,ll b,ll &x,ll &y){
if (!b){
x=1,y=0;
return a;
}
ll ans=exgcd(b,a%b,y,x);
y-=(a/b)*x;
return ans;
}
ll INV(ll a,ll b){ll x,y;return exgcd(a,b,x,y),(x%b+b)%b;}
ll crt(ll x,ll p,ll mod){return INV(p/mod,mod)*(p/mod)*x;}
ll FAC(ll x,ll a,ll b)
{if(!x)return 1;ll ans=1;for(ll i=1;i<=b;i++)if(i%a)ans*=i,ans%=b;
ans=pow_mod(ans,x/b,b);for(ll i=1;i<=x%b;i++)if(i%a)ans*=i,ans%=b;return ans*FAC(x/a,a,b)%b;}
ll C(ll n,ll m,ll a,ll b)
{ll N=FAC(n,a,b),M=FAC(m,a,b),Z=FAC(n-m,a,b),sum=0,i;for(i=n;i;i=i/a)sum+=i/a;
for(i=m;i;i=i/a)sum-=i/a;for(i=n-m;i;i=i/a)sum-=i/a;return N*pow_mod(a,sum,b)%b*INV(M,b)%b*INV(Z,b)%b;}
ll exlucas(ll n,ll m,ll p)
{ll t=p,ans=0,i;for(i=2;i*i<=p;i++){ll k=1;while(t%i==0){k*=i,t/=i;}
ans+=crt(C(n,m,i,k),p,k),ans%=p;}if(t>1)ans+=crt(C(n,m,t,t),p,t),ans%=p;return ans % p;}
ll H(ll x,ll p) //错排
{
ll ans=0;
if(x==0)return 1;
x=x%(2*p);
if(x==0)x=2*p;
for(int i=2;i<=x;++i)
ans=(ans*i+(i%2==0?1:-1))%p;
return (ans+p)%p;
}
map<ll ,ll> ph;
ll r,a[100009];
ll euler_phi(ll x) //直接求欧拉函数 //还有一种线性筛法
{
ll res=1;
for(ll i=2;i*i<=x;++i){
if(x%i==0){
x/=i;
res*=(i-1);
while(x%i==0){
x/=i;
res*=i;
}
}
}
if(x>1) res*=(x-1);
return res;
}
ll check(ll x,ll op){
if(x==1+r||op==1){
return 1;
}//
ll t=check(x+1,ph[op]);
return qqpp(a[x],t,op);
}
int main(){
ll n,m,t,l;
read(n);
read(m);
for(int i=1;i<=n;i++){
read(a[i]);
}
read(t);
ll cur=m;
while(cur!=1) ph[cur]=euler_phi(cur),cur=ph[cur];
ph[cur]=1;
while(t--){
//read(moddd);
read(l);
read(r);
printf("%lld\n",check(l,m)%m);
}
return 0;
}
摊牌了 学了一早上单调栈 单调队列 知道有这个玩意但是不会用
-
- (数学鸽了
2333矩阵快速幂
自己推一下初始矩阵【a0j a1j ----- anj 3】 和递推矩阵就好了
题目的n 是变化的 所以递推矩阵也是变化的 循环控制一下就好了
剩下的就是矩阵快速幂了(裸题)
#include<stdlib.h>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<time.h>
#include <cstdio>
#include <iostream>
#include <vector>
#define ll long long
#define int long long
#define inf 0x3f3f3f3f
#define mods 1000000007
#define modd 998244353
#define PI acos(-1)
#define fi first
#define se second
#define lowbit(x) (x&(-x))
#define mp make_pair
#define pb push_back
#define si size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
#define IOS ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
inline ll read(){char c=getchar();ll f=1,x=0;while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^'0');c=getchar();}return x*f;}
const int mod =1e7+7;
int aa,bb,n,m;
struct Matrix {
int a[13][13];
Matrix() { memset(a, 0, sizeof a); }
Matrix operator*(const Matrix &b) const {
Matrix res;
for (int i = 1; i <=n+2; ++i)
for (int j = 1; j <=n+2; ++j)
for (int k = 1; k <=n+2; ++k)
res.a[i][j] = (res.a[i][j] + a[i][k] * b.a[k][j]) % mod;
return res;
}
} ans, base;
void init() {
ans.a[1][1]=23;
for(int i=2;i<=n+1;i++){
ans.a[1][i]=read();
}
ans.a[1][n+2]=3; //n+2 行初始矩阵
for(int i=1;i<=n+1;i++){
base.a[1][i]=10;
base.a[n+2][i]=1;
}
base.a[1][n+2]=0;
base.a[n+2][n+2]=1;
for(int i=2;i<=n+1;i++){
for(int j=1;j<=n+1;j++){
if(j>=i){
base.a[i][j]=1;}
else{
base.a[i][j]=0;
}
}
}
}
/*
[p 1
q 0]*/
void qpow(int b) {
while (b) {
if (b & 1) ans = ans * base;
base = base * base;
b >>= 1;
}
}
signed main() {
while(scanf("%lld%lld",&n,&m)!=EOF){
init();
qpow(m);
printf("%lld\n",ans.a[1][n+1]%mod);
}
return 0;
}
CF 2200分数论题
题目给我们一个数 范围1e15 然后用这个数的约数作为节点值去建图 巴拉巴拉 - - 节点u与节点v建一条边的前提是 u%v=0 而且u/v∈prime 边权就是u/v 然后巴拉巴拉 给我们q组询问 问(u,v) 的最短路径数 %998244353
以上差不多就是题意 先自己画个图理解一下样例 1 吧
我们每次走u到gcd(u,v) 那么路径长度就是 u/(gcd(u,v)) 然后利用组合数去算 同理 gcd(u,v) 到v 也是如此 那么这个像图论的数论题就转化成了组合数问题 u–>gcd(u,v) 途中质因子一定是减少的,那么我们不管如何减少都不影响最终到目的地的结果,所有质因子的删除排列为总幂次的全排列,每次删除一种质因子 则分母就是 每个质因子幂次的全排列的乘积
贡献 (全部质因子幂次)! / Σ(单个质因子幂次)!
题目中模数是质数 所以根据费马小定理 可以得到 a/b%c=a*bc-2 %c
#include<stdlib.h>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<time.h>
#include <cstdio>
#include <iostream>
#include <vector>
#define ll long long
#define inf 0x3f3f3f3f
#define mods 998244353
#define modd 45445
#define PI acos(-1)
#define fi first
#define se second
#define lowbit(x) (x&(-x))
#define mp make_pair
#define pb push_back
#define si size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
#define IOS ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
ll gcd(ll a,ll b){if(a<0)a=-a;if(b<0)b=-b;return b==0?a:gcd(b,a%b);}
template<typename T>void read(T &res){bool flag=false;char ch;while(!isdigit(ch=getchar()))(ch=='-')&&(flag=true);
for(res=ch-48;isdigit(ch=getchar());res=(res<<1)+(res<<3)+ch - 48);flag&&(res=-res);}
ll lcm(ll a,ll b){return a*b/gcd(a,b);}
ll qp(ll a,ll b,ll mod){ll ans=1;if(b==0){return ans%mod;}while(b){if(b%2==1){b--;ans=ans*a%mod;}a=a*a%mod;b=b/2;}return ans%mod;}//快速幂%
ll qpn(ll a,ll b, ll p){ll ans = 1;a%=p;while(b){if(b&1){ans = (ans*a)%p;--b;}a =(a*a)%p;b >>= 1;}return ans%p;}//逆元 (分子*qp(分母,mod-2,mod))%mod;
ll fact_pow(ll n,ll p){ll res=0;while(n){n/=p;res+=n;}return res;}
ll mult(ll a,ll b,ll p)
{
a%=p;
b%=p;
ll r=0,v=a;
while(b)
{
if(b&1)
{
r=(r+v)%p;
r=(r+p)%p;
}
v<<=1;
v=(v+p)%p;
b>>=1;
}
return r%p;
}
ll pow_mod(ll x,ll n,ll mod)
{
ll res=1;
while(n)
{
if(n&1)
res=mult(res,x,mod);
x=mult(x,x,mod);
n>>=1;
}
return res;
}
ll quick_pow(ll a,ll b,ll p){ll r=1,v=a%p;while(b){if(b&1)r=mult(r,v,p);v=mult(v,v,p);b>>=1;}return r;}
bool CH(ll a,ll n,ll x,ll t)
{ll r=quick_pow(a,x,n);ll z=r;for(ll i=1;i<=t;i++){r=mult(r,r,n);if(r==1&&z!=1&&z!=n-1)return true;z=r;}return r!=1;}
bool Miller_Rabin(ll n)
{if(n<2)return false;if(n==2)return true;if(!(n&1))return false;ll x=n-1,t=0;while(!(x&1)){x>>=1;t++;}
srand(time(NULL));ll o=8;for(ll i=0;i<o;i++){ll a=rand()%(n-1)+1;if(CH(a,n,x,t))return false;}return true;}
ll exgcd(ll a,ll b,ll &x,ll &y){
if (!b){
x=1,y=0;
return a;
}
ll ans=exgcd(b,a%b,y,x);
y-=(a/b)*x;
return ans;
}
ll INV(ll a,ll b){ll x,y;return exgcd(a,b,x,y),(x%b+b)%b;}
ll crt(ll x,ll p,ll mod){return INV(p/mod,mod)*(p/mod)*x;}
ll FAC(ll x,ll a,ll b)
{if(!x)return 1;ll ans=1;for(ll i=1;i<=b;i++)if(i%a)ans*=i,ans%=b;
ans=pow_mod(ans,x/b,b);for(ll i=1;i<=x%b;i++)if(i%a)ans*=i,ans%=b;return ans*FAC(x/a,a,b)%b;}
ll C(ll n,ll m,ll a,ll b)
{ll N=FAC(n,a,b),M=FAC(m,a,b),Z=FAC(n-m,a,b),sum=0,i;for(i=n;i;i=i/a)sum+=i/a;
for(i=m;i;i=i/a)sum-=i/a;for(i=n-m;i;i=i/a)sum-=i/a;return N*pow_mod(a,sum,b)%b*INV(M,b)%b*INV(Z,b)%b;}
ll exlucas(ll n,ll m,ll p)
{ll t=p,ans=0,i;for(i=2;i*i<=p;i++){ll k=1;while(t%i==0){k*=i,t/=i;}
ans+=crt(C(n,m,i,k),p,k),ans%=p;}if(t>1)ans+=crt(C(n,m,t,t),p,t),ans%=p;return ans % p;}
ll H(ll x,ll p) //错排
{
ll ans=0;
if(x==0)return 1;
x=x%(2*p);
if(x==0)x=2*p;
for(int i=2;i<=x;++i)
ans=(ans*i+(i%2==0?1:-1))%p;
return (ans+p)%p;
}
const int manx=1e6+7;
//vector<ll>v[manx];
ll fac[manx/100];//质因子
ll rnm=0;
ll cnt=0,ans=1;
ll vis[150];
void check(ll d){
ll tmp=d;
for(ll i=2;i*i<=d;i++) {
if(tmp%i==0)fac[++rnm]=i;
while(tmp%i==0)tmp/=i;
}
if(tmp>1)fac[++rnm]=tmp;
}
int main(){
vis[0]=vis[1]=1;
for(int i=2;i<=100;i++){
vis[i]=vis[i-1]*i%mods; //预处理阶乘
}
ll D,q;
ll u,v,ways;
read(D);
check(D);
read(q);
while(q--){
ll sumad=0,sumal=1;
ll sumbd=0,sumbl=1;
ll a,b;
read(u);
read(v);
ways=gcd(u,v);
a=u/ways;
b=v/ways;
//总幂次 单独幂次
for(int i=1;i<=rnm;i++){
ll flag=0;
while(a%fac[i]==0){
a=a/fac[i];
flag++;
}
sumal=sumal*vis[flag]%mods;
sumad=sumad+flag;
}
sumad=vis[sumad];
for(int i=1;i<=rnm;i++){
ll flag=0;
while(b%fac[i]==0){
b=b/fac[i];
flag++;
}
sumbl=sumbl*vis[flag]%mods;
sumbd=sumbd+flag;
}
sumbd=vis[sumbd];
ll ans1=qp(sumal,mods-2,mods)*sumad%mods;
ll ans2=qp(sumbl,mods-2,mods)*sumbd%mods;
//ll ans=mult(ans1,ans2,mods);
//ll ans=ans1*ans2;
//printf("%lld %lld %lld\n",ans%mods,ans1,ans2);
//ll ans=mult(ans1,ans2,mods);
ll ans=ans1*ans2%mods;
printf("%lld\n",ans%mods);
}
return 0;
}
脑子里全是暴力n^2 CF1900数学
题目给了我们n个数 每个数都<=n 然后题目整了个循环移动
循环移动距离为d的话就是让数组所有元素右移动d个位置 如果越界了就移动到数组首部去 - - 自己理解下吧 定义P(i)=Σ |a[i]-i | 题目要我们求最小的P(i) 以及i 显然当时我头脑只能想到n^2 ---->肯定TLE
画个图吧 冷静分析
对于当前状态i 与下一个状态i+1 除了数组尾的元素外 其他元素的贡献变化无非是+1 或者 -1
我们用一个标记数组vis[] L=0 R=0 add=abs(a[i]-i)先记录初始输入时的数据 也就是 (a[i]-i)>0 时 vis[a[i]-i] ++ L++ 对于a[i]-i<=0 的 我们统计R++
显然 当前(移动距离为0时) L++的元素 下一次移动时(0+1) 他们产生的贡献是负的,而R++的那部分元素会产生正值贡献 绝对值自己体会体会吧
以上是预处理,接下来进入数组循环移动 枚举i=1到n-1
先是对add更新 减去L 再加上R 然后特殊的对上一次数组尾处理
也就是 -n+a[last] +a[last] -1 因为a[i]<=n 所以减去上一次的| a[n]-n | 我们直接开出来 然后处理 移位到数组首部 如此add 更新完成
(吐了,感觉我废话一大堆) 上代码自己思考吧 水题 &思维
#include<stdlib.h>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<time.h>
#include <cstdio>
#include <iostream>
#include <vector>
#define ll long long
#define inf 0x3f3f3f3f
#define mods 1000000007
#define modd 998244353
#define PI acos(-1)
#define fi first
#define se second
#define lowbit(x) (x&(-x))
#define mp make_pair
#define pb push_back
#define si size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
#define IOS ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
ll gcd(ll a,ll b){if(a<0)a=-a;if(b<0)b=-b;return b==0?a:gcd(b,a%b);}
template<typename T>void read(T &res){bool flag=false;char ch;while(!isdigit(ch=getchar()))(ch=='-')&&(flag=true);
for(res=ch-48;isdigit(ch=getchar());res=(res<<1)+(res<<3)+ch - 48);flag&&(res=-res);}
ll lcm(ll a,ll b){return a*b/gcd(a,b);}
ll qp(ll a,ll b,ll mod){ll ans=1;if(b==0){return ans%mod;}while(b){if(b%2==1){b--;ans=ans*a%mod;}a=a*a%mod;b=b/2;}return ans%mod;}//快速幂%
ll qpn(ll a,ll b, ll p){ll ans = 1;a%=p;while(b){if(b&1){ans = (ans*a)%p;--b;}a =(a*a)%p;b >>= 1;}return ans%p;}//逆元 (分子*qp(分母,mod-2,mod))%mod;
ll fact_pow(ll n,ll p){ll res=0;while(n){n/=p;res+=n;}return res;}
ll mult(ll a,ll b,ll p)
{
a%=p;
b%=p;
ll r=0,v=a;
while(b)
{
if(b&1)
{
r=(r+v)%p;
r=(r+p)%p;
}
v<<=1;
v=(v+p)%p;
b>>=1;
}
return r%p;
}
ll pow_mod(ll x,ll n,ll mod)
{
ll res=1;
while(n)
{
if(n&1)
res=mult(res,x,mod);
x=mult(x,x,mod);
n>>=1;
}
return res;
}
ll quick_pow(ll a,ll b,ll p){ll r=1,v=a%p;while(b){if(b&1)r=mult(r,v,p);v=mult(v,v,p);b>>=1;}return r;}
bool CH(ll a,ll n,ll x,ll t)
{ll r=quick_pow(a,x,n);ll z=r;for(ll i=1;i<=t;i++){r=mult(r,r,n);if(r==1&&z!=1&&z!=n-1)return true;z=r;}return r!=1;}
bool Miller_Rabin(ll n)
{if(n<2)return false;if(n==2)return true;if(!(n&1))return false;ll x=n-1,t=0;while(!(x&1)){x>>=1;t++;}
srand(time(NULL));ll o=8;for(ll i=0;i<o;i++){ll a=rand()%(n-1)+1;if(CH(a,n,x,t))return false;}return true;}
ll exgcd(ll a,ll b,ll &x,ll &y){
if (!b){
x=1,y=0;
return a;
}
ll ans=exgcd(b,a%b,y,x);
y-=(a/b)*x;
return ans;
}
ll INV(ll a,ll b){ll x,y;return exgcd(a,b,x,y),(x%b+b)%b;}
ll crt(ll x,ll p,ll mod){return INV(p/mod,mod)*(p/mod)*x;}
ll FAC(ll x,ll a,ll b)
{if(!x)return 1;ll ans=1;for(ll i=1;i<=b;i++)if(i%a)ans*=i,ans%=b;
ans=pow_mod(ans,x/b,b);for(ll i=1;i<=x%b;i++)if(i%a)ans*=i,ans%=b;return ans*FAC(x/a,a,b)%b;}
ll C(ll n,ll m,ll a,ll b)
{ll N=FAC(n,a,b),M=FAC(m,a,b),Z=FAC(n-m,a,b),sum=0,i;for(i=n;i;i=i/a)sum+=i/a;
for(i=m;i;i=i/a)sum-=i/a;for(i=n-m;i;i=i/a)sum-=i/a;return N*pow_mod(a,sum,b)%b*INV(M,b)%b*INV(Z,b)%b;}
ll exlucas(ll n,ll m,ll p)
{ll t=p,ans=0,i;for(i=2;i*i<=p;i++){ll k=1;while(t%i==0){k*=i,t/=i;}
ans+=crt(C(n,m,i,k),p,k),ans%=p;}if(t>1)ans+=crt(C(n,m,t,t),p,t),ans%=p;return ans % p;}
ll H(ll x,ll p) //错排
{
ll ans=0;
if(x==0)return 1;
x=x%(2*p);
if(x==0)x=2*p;
for(int i=2;i<=x;++i)
ans=(ans*i+(i%2==0?1:-1))%p;
return (ans+p)%p;
}
const int maxn=2e6+7;
ll a[maxn],vis[maxn],l=0,r=0;
int main(){
ll n,ans=0,flag;
read(n);
ll add=0;
ll ls=n;
for(int i=1;i<=n;i++){
read(a[i]);
add=add+abs(a[i]-i); //0次移动
if(i==n){
continue;
}
if(a[i]-i>0){
vis[a[i]-i]++;
l++; //绝对值过大 下标移动要减
}
else{
r++ ;//abs增加
}
}
ans=add;
flag=0;
for(int i=1;i<n;i++){
add=add-l+r+a[ls]-1-n+a[ls]; //维护当前移动距离
if(add<ans){
ans=add;
flag=i;
}
r=r+vis[i]; // a[x]-x =1 初始 当前移动1 说明 此时a[x] -x' =0 下一次移动增加值
l=l-vis[i];
if(a[ls]!=1){
//-1 -2 无负数 下一次必定减
r--;
l++;
}
vis[a[ls]-1+i]++;
ls--;
}
printf("%lld %lld",ans,flag);
}
人类悲欢,各不相同