2839: 假裝這是簽到題
Time Limit: 2000 MS Memory Limit: 262144 KB
Total Submit: 39 Accepted: 9 Page View: 153
Submit Status Discuss
Description
對於線性方程組求是一個十分有趣的而又實用的技能,一般解線性方程組的方法有五種分別爲:
第一種 消元法 ,此法 最爲簡單,直接消掉只剩最後一個未知數,再回代求餘下的未知數,但只適用於未知數個數等於方程的個數,且有解的情況.
第二種 克拉姆法則,如果行列式不等於零,則用常數向量替換系數行列式中的每一行再除以係數行列式,就是解;
第三種 逆矩陣法,同樣要求係數矩陣可逆,直接建立AX=b與線性方程組的關係,X=A^-1.*b就是解
第四種 增廣矩陣法,利用增廣矩陣的性質(A,b)通過線性行變換,化爲簡約形式,確定自由變量,(各行中第一個非零元對應的未知數除外餘下的就是自由變量),對自由變量進行賦值,求出其它未知數,然後寫成基礎解析的形式,最後寫出通解.
這種方法需要先判別:增廣矩陣的秩是否等於係數矩陣的秩,相等且小於未知數個數,則無窮多解;等於未知數個數,唯一解.秩不想等,無解.
第五種 計算機編程,隨便用個軟件,譬如Matlab,輸入密令,
問:給你一個等比數列,求前 n項和,對 998424353 取模。
Input
第一行一個整數 T
(T≤105) ,表示有 T
組測試數據 。
對於每組測試數據:
輸入三個整數 a,q,n,分別表示數列第一項,公比,前多少項, (|a|≤109,|q|≤109,(q≠0),n≤109) (|a|代表 a的絕對值)。
Output
對於每組測試數據,輸出一個整數,表示該等比數列的前 n
項和。
3
2 2 3
3 2 500
-1 2 3
14
728273816
998424346
此題最大的坑點就是這個mod,一個不小心就發現不了這個mod不是素數,這個可以被43,137,5891整除,如果直接用公式算逆元的話會出問題的,第二組測試樣列就可以驗證(暴力算出來是不等的),逆元的條件是互素,不滿足,因爲n爲1e9,所以全部暴力也是不可能的,所以我們想到了二分。
我們已n=5或4爲例:
= =
= =
推廣到n
= n爲奇數
= n爲偶數
所以得到公式:
ll RNG(int q,int n)
{
if(n==1)return 1;
if(n%2==0)return RNG(q,n/2)*(1+quick_pow(q,n/2))%mod;
else return RNG(q,n/2)*(1+quick_pow(q,n/2))%mod+quick_pow(q,n-1);
}
因爲一個快速冪的的複雜度爲 log(n)所以整體的的複雜度爲 log^2 (n) 問題不大。
另外: 不知道這個想法偏不偏,但是想到了的話這個題也是簡單題,只要發現這個mod不是素數然後想到二分來算就完事。在這題的數據方面,第一組中有一個數據的q=1的時候,用逆元來算的話會錯,需要特判一下才能過第一組數據,但是第二組數據就不行啦,我專門寫的一個小的數據,讓暴力很快就可以跑出答案的數據發現問題,第三組數據是1e9的數據專門卡暴力的,第四組是t=1e5的,不爲別的就卡你cin cout2333333。賽前預期:前期會有幾個人手速及快用逆元的方法來做,然後wa好多次,後面發現問題想了一會用二分過了,後面就會有人陸陸續續的過,也有人死磕wa十幾次怎麼都想不到正解,也有人一上來就發現mod有問題,但是想不到正解,本以爲在賽場上一共會提交50-100次,然後差不多五個人過題但是..
沒想到全場沒一個人過,wa了好多次,好多人都沒有提交,可能是想不到正解也可能寫完了不敢交。
是我太壞了,但是ICPC是殘酷的你想得到就可以拿銀,想不到就是鐵,lwp和zq給我驗題的時候都是直接想到了二分過了,所以ACM任重而道遠啊。
代碼:
#include<bits/stdc++.h>
#define ll long long
#define qq printf("QAQ\n");
using namespace std;
const int maxn=1e5+5;
const int mod=998424353;
const int inf=0x3f3f3f3f;
ll quick_pow(ll a,int n)
{
ll ans=1;
while(n)
{
if(n&1)ans=ans*a%mod;
n/=2;
a=a*a%mod;
}
return ans;
}
ll RNG(int q,int n)
{
if(n==1)return 1;
if(n%2==0)return RNG(q,n/2)*(1+quick_pow(q,n/2))%mod;
else return RNG(q,n/2)*(1+quick_pow(q,n/2))%mod+quick_pow(q,n-1);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ll a,n,q;
scanf("%lld%lld%lld",&a,&q,&n);
printf("%lld\n",(a*RNG(q,n)%mod+mod)%mod);
}
return 0;
}