跳骚
题目大意
有一只跳骚,有一张卡片,卡片上有n+1个自然数,最后且最大的一个数是m,前面的n个数都比m小。跳骚可以向左向右跳,但是跳的步数只能是卡片上的数字。如果跳骚可以跳到它初始位置的左边一个位置,那就说这张卡片是成功的。给定n和m,问你有几张成功的卡片。
思路
我们设第i张卡片的值为Di,使用的次数为Xi(Xi的正负代表跳骚跳的方向),则Di和Xi应该满足以下关系
代码
#include <iostream>
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define mod 1000000007
#define lmax 1000
#define pi 3.141592653589793238462643383279
#define eps 1e-7
using namespace std;
typedef long long ll;
typedef __int128 inta;
void scan(__int128 &x)//输入
{
x=0;int f=1;char ch=getchar();
while (!isdigit(ch)){if (ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
x*=f;
}
inline void print(__int128 x)//输出
{
if(x<0){
putchar('-');
x=-x;
}
if(x>9) print(x/10);
putchar(x%10+'0');
}
typedef struct
{
inta num,many;
}node;
node factor[10000];
inta total;
inta powe(inta x,inta y);
void generation_factors(inta x);
int main()
{
inta n,m,sum;
int t;
scanf("%d",&t);
while(t--)
{
scan(n);
scan(m);
sum=0;
generation_factors(m);
for(inta i=total;i>=0;i--)
{
if(factor[i].many%2)
sum-=powe(m/factor[i].num,n);
else
sum+=powe(m/factor[i].num,n);
}
print(sum);
printf("\n");
}
return 0;
}
inta powe(inta x,inta y)//计算x的y次方的值
{
inta temp;
temp=x;
for(inta i=1;i<y;i++)
temp*=x;
return temp;
}
void generation_factors(inta x)//生成x的所有因子
{
total=0;
factor[0].num=1;
factor[0].many=0;
for(inta i=2;i*i<=x;i++)
{
if(x%i==0)
{
while(!(x%i))
x/=i;
for(inta j=0;j<=total;j++)
{
factor[total+1+j].num=i*factor[j].num;
factor[total+1+j].many=factor[j].many+1;
}
total=total*2+1;
}
}
if(x!=1)
{
for(inta i=0;i<=total;i++)
{
factor[total+i+1].num=x*factor[i].num;
factor[total+i+1].many=factor[i].many+1;
}
total=total*2+1;
}
}
幸运数字
题目大意
给定一个数字n,让你求出最少几个连续的8能整除n,如果没有则输出"0"。
思路
首先构造一个全8数字为[8/9*(10x-1)],其中x为全8数字的位数,那么原题就变成求最小的x,满足题目条件。
这里面我打错号的两个式子是错的,应该将9/8改为8/9.
代码
#include <iostream>
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
//#define mod 1000000007
#define lmax 1000
#define pi 3.141592653589793238462643383279
#define eps 1e-7
using namespace std;
typedef long long ll;
//typedef __int128 inta;
ll mod(ll a,ll b,ll c);
ll modd(ll a,ll b,ll c);
void generation_factors(ll x);
ll gcd(ll a,ll b);
ll phi(ll x);
ll c[10000];
ll many;
int main()
{
ll n,l,m,minn;
int tcase=0;
while(~scanf("%lld",&n))
{
if(n==0)
break;
printf("Case %d:",++tcase);
l=9*n/gcd(n,8);
minn=l+1;
if(!(l%2)||!(l%5))//这里一开始一直没看懂,应该是和公式中的10有关,2和5都是10的因数
{
printf("0无解\n");
continue;
}
m=phi(l);
generation_factors(m);
for(int i=1;i<=many;i++)
{
if(c[i]<minn&&modd(10,c[i],l)==1)
minn=c[i];
}
printf("%lld\n",minn);
}
return 0;
}
ll mod(ll a,ll b,ll c)//特殊处理的a*b mod c求值运算
{
ll t1,t2,t3,t4,k=1000000,temp;
t1=a/k;
t2=a%k;
t3=b/k;
t4=b%k;
temp=(((k*k)%c)*((t1*t3)%c)+(t2*t3)%c*k%c+(t1*t4)%c*k%c+(t2*t4)%c)%c;
return temp;
}
ll gcd(ll a,ll b)//辗转相除求最大公因数
{
if(a<b)swap(a,b);
if(b==0)
return a;
return gcd(b,a%b);
}
ll phi(ll x)//求x的欧拉函数值
{
ll temp=x;
for(int i=2;i*i<=x;i++)
{
if(x%i==0)
{
while(x%i==0)
x/=i;
temp=temp/i*(i-1);
}
}
if(x!=1)
temp=temp/x*(x-1);
return temp;
}
void generation_factors(ll x)//生成x的所有因子,结果保存在c数组里
{
ll ss,sk;
c[1]=1;
many=1;
for(ll i=2;i*i<=x;i++)
{
if(!(x%i))
{
ss=1;
while(!(x%i))
{
sk=many;
for(ll j=ss;j<=sk;j++)
{
c[++many]=c[j]*i;
}
x/=i;
ss=sk+1;
}
}
}
sk=many;
if(x!=1)
for(ll i=1;i<=sk;i++)
c[++many]=c[i]*x;
}
ll modd(ll a,ll b,ll c)//快速计算a的b次方模c的值
{
ll ans,temp;
ans=1;
temp=a%c;
while(b!=0)
{
if(b%2)
ans=mod(ans,temp,c);
temp=mod(temp,temp,c);
b/=2;
}
return ans;
}
解方程
题目大意
给一个质数P,问是否存在正整数N,M使得N3+P*N2=M3。
如果存在,输出yes,否则输出no。
思路
代码
里面有二分查找的函数代码。
#include <iostream>
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define mod 1000000007
#define lmax 1000
#define pi 3.141592653589793238462643383279
#define eps 1e-7
using namespace std;
typedef long long ll;
ll binary__search(ll p);
int main()
{
ll p;
int t;
scanf("%d",&t);
while(t--)
{
scanf("%lld",&p);
if(binary__search(p))
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
ll binary__search(ll p)
{
ll minn=1,maxx=20000000000,mid,temp;
mid=(maxx+minn)/2;
while(minn<=maxx)
{
temp=3*mid*mid+3*mid+1;
if(temp==p)
return mid;
if(temp<p)
minn=mid+1;
else
maxx=mid-1;
mid=(minn+maxx)/2;
}
return 0;
}