链接:戳这里
Lucky
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
问题描述
Vampire喜欢玄学,尤其喜欢研究幸运数字.
对于一个数字集合S,定义关于S的幸运数字为无法用S中的数相加得到的最小的非负整数(每个数可以使用任意次).
现在给定一个数集,如果能使用其中的数相加得到任意自然数,输出”YES”,否则输出”NO”.
输入描述
第一行一个正整数T,为数据组数.
每组数据第一行一个n,表示集合大小.
接下来n个数,表示该数集里的数.
1≤n≤10^5,1≤T≤10,0≤ai≤10^9
输出描述
每组数据回答一个”YES”或”NO”.
输入样例
1
1
2
输出样例
NO
思路:
因为每个数可以用很多次,所以只要这个集合中有1,那么就可以加出所有的数来.注意最后要判定一下是否有0.
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n;
int a[1000100];
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
int flag1=0,flag2=0;
for(int i=1;i<=n;i++) {
scanf("%d",&a[i]);
if(a[i]==1){
flag1=1;
}
if(a[i]==0){
flag2=1;
}
}
if(flag1 && flag2) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
Segment
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
问题描述
Rivendell非常神,喜欢研究奇怪的问题.
今天他发现了一个有趣的问题.找到一条线段x+y=qx+y=q,令它和坐标轴在第一象限围成了一个三角形,然后画线连接了坐标原点和线段上坐标为整数的格点.
请你找一找有多少点在三角形的内部且不是线段上的点,并将这个个数对PP取模后告诉他.
输入描述
第一行一个数T,为测试数据组数.
接下来每一行两个数qq,PP,意义如题目中所示.
q是质数且q≤10^18,1≤P≤10^18,1≤T≤10.
输出描述
对每组数据,输出点的个数模PP后的值.
输入样例
1
2 107
输出样例
0
思路:
考虑一条以(0,0)为起点,(x,y)为终点的线段上格点的个数(不包含端点时),一定是gcd(x,y)-1,这个很显然吧.
然后整个网格图范围内的格点数目是q*(q-1)/2
所以答案就是q*(q-1)/2 − 所有线段上的格点的个数.
因为q是质数且a+b=q可以推出gcd(a,b)=1
显然答案就是计算等腰直角三角形中的格点数
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
ll Q,P;
ll kuai(ll q,ll num,ll mod){
ll ans=0;
ll base=q;
while(num){
if(num%2) ans=(ans+base)%mod;
num/=2;
base=(base+base)%mod;
}
return ans%mod;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
cin>>Q>>P;
ll ans=(Q-1)/2;
ans=kuai(ans,Q-2,P);
cout<<(ans+P)%P<<endl;
}
return 0;
}
Sequence
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
问题描述
Lcomyn 是个很厉害的选手,除了喜欢写17kb+的代码题,偶尔还会写数学题.他找到了一个数列:
他给了你几个数:nn,aa,bb,cc,你需要告诉他fn模p后的数值.
输入描述
第一行一个数T,为测试数据组数.
每组数据一行,一行五个正整数,按顺序为nn,aa,bb,cc,pp.
1≤T≤10,1≤n≤10^18 ,1≤a,b,c≤10^9 ,p是质数且 p≤10^9 +7.
输出描述
对每组数据输出一行一个数,输出fn对p取模后的数值.
输入样例
1
5 3 3 3 233
输出样例
190
思路:
观察递推式我们可以发现,所有的 fi都是a的幂次,所以我们可以对fi取一个以a为底的log
即gi=log(a,fi)
那么递推式变成gi =b+c∗g[i−1]+g[i−2]
,这个式子可以矩阵乘法
这题有一个小trick,注意a mod p=0的情况.
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include <ctime>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<iomanip>
#include<cmath>
#define mst(ss,b) memset((ss),(b),sizeof(ss))
#define maxn 0x3f3f3f3f
#define MAX 1000100
///#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef unsigned long long ull;
#define INF (1ll<<60)-1
using namespace std;
struct Matrix{
ll ma[3][3];
Matrix(){
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
ma[i][j]=0;
}
};
ll n,A,B,C,P;
Matrix Mult(Matrix b,Matrix a,ll p){
Matrix ans;
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
for(int k=0;k<3;k++){
ans.ma[i][j]=(ans.ma[i][j]+a.ma[i][k]*b.ma[k][j]%p)%p;
}
}
}
return ans;
}
Matrix MPow(Matrix a,ll num,ll p){
Matrix tmp;
for(int i=0;i<3;i++) tmp.ma[i][i]=1;
while(num){
if(num%2) tmp=Mult(tmp,a,p);
a=Mult(a,a,p);
num/=2;
}
return tmp;
}
ll Pow(ll a,ll b,ll p){
ll ans=1;
while(b){
if(b%2) ans=ans*a%p;
a=a*a%p;
b/=2;
}
return ans;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
cin>>n>>A>>B>>C>>P;
Matrix a,b;
a.ma[0][0]=1;a.ma[2][0]=B;
b.ma[0][0]=1;b.ma[1][2]=1;
b.ma[2][0]=B;b.ma[2][1]=1;b.ma[2][2]=C;
if(n==1) cout<<1<<endl;
else if(n==2) printf("%I64d\n",Pow(A,B,P));
else {
if(A%P==0) cout<<0<<endl;
else {
Matrix tmp=MPow(b,n-2,P-1);
Matrix ans=Mult(a,tmp,P-1);
ll anw=Pow(A,ans.ma[2][0],P);
printf("%I64d\n",anw);
}
}
}
return 0;
}<strong>
</strong>