2 条题解

  • 0
    @ 2026-6-11 21:28:53

    也可以把分子和分母列成二阶矩阵后做矩阵快速幂。

    #include<bits/stdc++.h>
    #define int long long
    #define rep(i,a,b) for(int i(a);i<=(b);++i)
    #define req(i,a,b) for(int i(a);i>=(b);--i)
    #define sort stable_sort
    constexpr int mod=100000007,B=1145;
    using namespace std;
    char buf[1<<23],*p1=buf,*p2=buf;
    #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    template<typename TP> inline TP read(TP &num)
    {
    	TP x=0;
    	int f=0;
    	char ch=getchar();
    	while(ch<48||ch>57) f|=ch=='-',ch=getchar();
    	while(48<=ch&&ch<=57) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    	return num=f?-x:x;
    }
    template<typename TP> inline TP read_mod(TP &num)
    {
    	TP x=0;
    	int f=0;
    	char ch=getchar();
    	while(ch<48||ch>57) f|=ch=='-',ch=getchar();
    	while(48<=ch&&ch<=57) x=((x<<1)+(x<<3)+(ch^48))%mod,ch=getchar();
    	return num=f?-x:x;
    }
    template<typename ...Args> inline void read(Args &...args)
    {
    	(read(args),...);
    }
    template<typename TP> inline void write(TP x)
    {
    	(x<0)?(putchar('-'),x=-x):0;
    	(x>9)?(write(x/10),0):0;
    	putchar((x%10)^48);
    }
    template<typename TP> inline void writeln(TP x)
    {
    	write<TP>(x);
    	puts("");
    }
    inline int qpow(int a,int b)
    {
    	a%=mod;
    	int res=1;
    	while(b)
    	{
    		if(b&1) res=res*a%mod;
    		a=a*a%mod;
    		b>>=1;
    	}
    	return res;
    }
    struct mat
    {
    	int a00,a01,a10,a11;
    	mat(int b00=0,int b01=0,int b10=0,int b11=0):a00(b00),a01(b01),a10(b10),a11(b11){}
    	mat operator*(const mat &b) const
    	{
    		return mat((a00*b.a00+a01*b.a10)%mod,(a00*b.a01+a01*b.a11)%mod,(a10*b.a00+a11*b.a10)%mod,(a10*b.a01+a11*b.a11)%mod);
    	}
    	mat operator^(int b) const
    	{
    		mat res(1,0,0,1),a(*this);
    		while(b)
    		{
    			if(b&1) res=res*a;
    			a=a*a;
    			b>>=1;
    		}
    		return res;
    	}
    } P[B];
    inline pair<string,int> strdiv(string s,int k)
    {
    	string q; int res=0;
    	for(char c:s)
    	{
    		res=res*10+(c^48);
    		if(!q.empty()||res>=k) q.push_back((res/k)^48);
    		res%=k;
    	}
    	if(q.empty()) q.push_back('0');
    	return {q,res};
    }
    inline string strsub(string s)
    {
    	string res=s;
    	int i=(int)res.size()-1;
    	while(i>=0&&res[i]=='0') res[i]='9',--i;
    	if(i>=0) res[i]--;
    	if(res[0]=='0'&&res.size()>1) res.erase(res.begin());
    	if(res.empty()) res.push_back('0');
    	return res;
    }
    signed main()
    {
    #ifndef LOCAL
    	freopen("calc.in","r",stdin);
    	freopen("calc.out","w",stdout);
    #endif
    	P[0]=mat(1,0,0,1);
    	rep(i,1,B-1) P[i]=P[i-1]*mat(2023,i*i%mod,i,833);
    	int T; cin>>T; while(T--)
    	{
    		string ns; cin>>ns; string sn=strsub(ns);
    		int n=0;
    		for(char c:ns) n=((n<<1)+(n<<3)+(c^48))%mod;
    		auto [q,r]=strdiv(sn,B);
    		mat mt=mat(1,0,0,1);
    		for(auto c:q) mt=(mt^10)*(P[B-1]^(c^48));
    		mt=mt*P[r];
    		writeln(((mt.a00*n%mod+mt.a01)*qpow(mt.a10*n+mt.a11,mod-2)%mod+mod)%mod);
    	}
    	return 0;
    }
    
    • 0
      @ 2025-9-10 17:20:08

      设取模前的答案为 f(n)f(n)。

      打表可知,当 n≥120n \ge 120 时,f(n)≡40176944(mod108+7)f(n)\equiv 40176944 \pmod {10^8+7}。

      根据以上性质,我们直接对 n>1000n>1000 的情况按照 n=1000n=1000 暴力计算即可。

      (实际上,这一性质是可以严格证明的,过程如下:)

      $$\begin{aligned} x \otimes 119 &=\dfrac{119^2+2023x}{833+119x} \\ &=\dfrac{14161+2023x}{833+119x} \\ &=\dfrac{2023(7+x)}{119(7+x)} \\ &=\dfrac{2023}{119} \\ &=17 \end{aligned}$$$$\begin{aligned} f(n) &=n \otimes (n-1) \otimes (n-2) \otimes \ldots \otimes 1 \\ &=((n \otimes (n-1) \otimes (n-2) \otimes \ldots \otimes 120) \otimes 119) \otimes 118 \otimes 117 \otimes \ldots \otimes 1 \\ &=17 \otimes 118 \otimes 117 \otimes \ldots \otimes 1 \\ &\equiv 40176944 \pmod {10^8+7} \end{aligned}$$
      #include <bits/stdc++.h>
      using namespace std;
      const int P = 1e8 + 7;
      int read()
      {
      	int x = 0;
      	char c = getchar_unlocked();
      	while (c < '0') c = getchar_unlocked();
      	while (c >= '0')
      	{
      		x = x * 10 + c - '0';
      		c = getchar_unlocked();
      		x = min(x, 1000);
      	}
      	return x;
      }
      int divs(int a, int b, int p = P)
      {
      	if (b % a == 0) return b / a;
      	int x = divs(p % a, a - b % a, a);
      	return (1ll * x * p + b) / a;
      }
      long long calc(long long x, long long y)
      {
      	return divs((833 + x * y) % P, (y * y + 2023 * x) % P);
      }
      signed main()
      {
      	freopen("calc.in", "r", stdin);
      	freopen("calc.out", "w", stdout);
      	int T = read();
      	while (T--)
      	{
      		int n = read();
      		int res = n;
      		for (int i = n - 1; i >= 1; i--)
      			res = calc(res, i);
      		cout << res << endl;
      	}
      	return 0;
      }
      
      • 1

      信息

      ID
      158
      时间
      1000ms
      内存
      512MiB
      难度
      4
      标签
      递交数
      18
      已通过
      7
      上传者