“盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛
来源:互联网 发布:angularjs.js 2.0下载 编辑:程序博客网 时间:2024/04/29 12:51
下面是部分题的题解。
前五题应该没什么太大问题,只贴上我比赛时的代码
第一题:黑白图像直方图
#include <cstdio>#include <cmath>#include <iostream>#include <queue>#include <cstring>#include <algorithm>using namespace std;#define mst(a,b) memset((a),(b),sizeof(a))#define f(i,a,b) for(int i=(a);i<=(b);++i)#define rush() int T;scanf("%d",&T);while(T--)typedef long long ll;const int maxn= 1005;const ll mod = 1e9+7;const int INF = 0x3f3f3f3f;const double eps = 1e-6;int a[maxn][maxn];int ans[maxn];int main(){ int n,m; while(~scanf("%d%d",&n,&m)) { mst(ans,0); for(int i=0;i<n;i++) for(int j=0;j<m;j++) { scanf("%d",&a[i][j]); } for(int i=0;i<m;i++) { for(int j=0;j<n;j++) { ans[i]+=(a[j][i]==1); } } for(int i=0;i<m-1;i++) { printf("%d ",ans[i]); } printf("%d\n",ans[m-1]); } return 0;}
第二题:神无月排位赛
#include <cstdio>#include <cmath>#include <iostream>#include <queue>#include <cstring>#include <algorithm>using namespace std;#define mst(a,b) memset((a),(b),sizeof(a))#define f(i,a,b) for(int i=(a);i<=(b);++i)#define rush() int T;scanf("%d",&T);while(T--)typedef long long ll;const int maxn= 100005;const ll mod = 1e9+7;const int INF = 0x3f3f3f3f;const double eps = 1e-6;char c[5]= {'D','C','B','A','S'};int main(){ int n; while(~scanf("%d",&n)) { int sum=0; int now=0; int a,b,c; int x; for(int i=1; i<=n; i++) { scanf("%d",&x); if(x==1) sum+=10; else sum-=5; if(sum<0) sum=0; if(sum>=100) { if(i<n) { i++; scanf("%d",&a); if(i<n) { i++; scanf("%d",&b); if(a==1&&b==1) { now++; sum=0; } else if(a==0&&b==0) { sum=60; } else { if(i<n) { i++; scanf("%d",&c); if(c==1) { now++; sum=0; } else { sum=60; } } } } } } } if(now>4) now=4; if(now==0) puts("D"); if(now==1) puts("C"); if(now==2) puts("B"); if(now==3) puts("A"); if(now==4) puts("S"); } return 0;}
第三题:I Love ces
#include <cstdio>#include <cmath>#include <iostream>#include <queue>#include <cstring>#include <algorithm>using namespace std;#define mst(a,b) memset((a),(b),sizeof(a))#define f(i,a,b) for(int i=(a);i<=(b);++i)#define rush() int T;scanf("%d",&T);while(T--)typedef long long ll;const int maxn= 100005;const ll mod = 1e9+7;const int INF = 0x3f3f3f3f;const double eps = 1e-6;int a[10];char s[maxn];//i love cesint main(){ while(~scanf("%s",s)) { mst(a,0); int len=strlen(s); for(int i=0;i<len;i++) { if(s[i]=='i'||s[i]=='I') a[0]++; if(s[i]=='l'||s[i]=='L') a[1]++; if(s[i]=='o'||s[i]=='O') a[2]++; if(s[i]=='v'||s[i]=='V') a[3]++; if(s[i]=='e'||s[i]=='E') a[4]++; if(s[i]=='c'||s[i]=='C') a[5]++; if(s[i]=='s'||s[i]=='S') a[6]++; } a[4]/=2; sort(a,a+6); printf("%d\n",a[0]); } return 0;}
第四题:添加好友
#include <cstdio>#include <cmath>#include <iostream>#include <queue>#include <cstring>#include <algorithm>using namespace std;#define mst(a,b) memset((a),(b),sizeof(a))#define f(i,a,b) for(int i=(a);i<=(b);++i)#define rush() int T;scanf("%d",&T);while(T--)typedef long long ll;const int maxn= 105;const ll mod = 1e9+7;const int INF = 0x3f3f3f3f;const double eps = 1e-6;ll n;ll fast_mod(ll a,ll b,ll c){ ll ans=1; a%=c; while(b) { if(b&1) ans=(ans*a)%c; b>>=1; a=(a*a)%c; } return ans;}int main(){ while(~scanf("%lld",&n)) { ll ans=fast_mod(2,n,mod); ans=(ans-1+mod)%mod; printf("%lld\n",ans); } return 0;}
第五题:字符串进制转换
#include <cstdio>#include <cmath>#include <iostream>#include <queue>#include <cstring>#include <algorithm>using namespace std;#define mst(a,b) memset((a),(b),sizeof(a))#define f(i,a,b) for(int i=(a);i<=(b);++i)#define rush() int T;scanf("%d",&T);while(T--)typedef long long ll;const int maxn= 100005;const ll mod = 1e9+7;const int INF = 0x3f3f3f3f;const double eps = 1e-6;ll power(ll a, ll n){ ll ans=1; while(n) { if(n&1) ans*=a; a*=a; n>>=1; } return ans;}/*ll solve(ll n,ll x){ return n-(x*(n/x));}*/char s[maxn];int a[maxn];ll m;int main(){ while(~scanf("%s%lld",s,&m)) { ll ans=0; int len=strlen(s); if(len==1&&s[0]=='a') //特别注意这个特判 { puts("0"); continue; } for(int i=0;i<len;i++) { ans+=(s[len-1-i]-'a')*power(26,i); } int cnt=0; while(ans) { a[cnt++]=ans%m; ans/=m; } for(int i=cnt-1;i>=0;i--) { printf("%d",a[i]); } puts(""); } return 0;}
第六题:
A序列
时间限制: 1000ms 内存限制: 128M
如果一个序列有奇数个正整数组成,不妨令此序列为
比如1 2 5 4 3就是一个A序列。
现在Jazz有一个长度为
比如1 2 5 4 3 6 7 8 9,最长的A序列子串是1 2 5 43。
多组输入,每组两行。
第一行是
第二行有
每组输入输出一行,即最长的A序列子串的长度。
1
9
1 2 5 4 3 6 7 8 9
样例输出1
5
【分析】根据题意我们可以枚举中间那个点,然后算出这个点左边(包含这个点)的最长单调子序列长度以及这个点右边(包含这个点)的长单调递减子序列长度取最小值就是要求的以该点为中心的A序列的最长长度的“一半”,每个点扫一遍即可。
求最长递增子序列用一下模板即可,求最长递减子序列只要逆过来求一下最长单调子序列就好了。
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define mst(a,b) memset((a),(b),sizeof(a))#define f(i,a,b) for(int i=(a);i<=(b);++i)#define rush() int T;scanf("%d",&T);while(T--)typedef long long ll;const int maxn= 50005;const ll mod = 1e9+7;const int INF = 0x3f3f3f3f;const double eps = 1e-6;int num[maxn];int temp[maxn];int ans[maxn];int l[maxn];int r[maxn];int main(){ int n; while(~scanf("%d",&n)) { for(int i=1; i<=n; i++) { scanf("%d",&num[i]); } int Max=1; mst(temp,0x3f); temp[0]=-1; for(int i=1; i<=n; i++) //求最长单调递增子序列 { int pos=lower_bound(temp,temp+n,num[i])-temp; temp[pos]=num[i]; Max=max(Max,pos); l[i]=Max; } Max=1; mst(temp,0x3f); temp[0]=-1; for(int i=n; i>=1; i--) //求单调递减子序列 { int pos=lower_bound(temp,temp+n,num[i])-temp; temp[pos]=num[i]; Max=max(Max,pos); r[i]=Max; } int ans=1; for(int i=1;i<=n;i++) { ans=max(ans,min(l[i],r[i])); } printf("%d\n",ans*2-1); } return 0;}
第七题:
战斗
时间限制: 2000ms 内存限制: 128M
最近,盛大计划开发一款手游,以下是简化版。系统和我方各有
所有怪兽是每秒攻击一次,即如果A和B战斗,A受到B的伤害的同时,B也受到A的伤害,直到一方死亡,换序列中的下一个怪兽,继续战斗。
第一行一个整数
对于每组数据,第一行输入一个整数
接下来
接下来
每组数据输出一行。如果我方可以通过合理安排怪兽的出战序列,保证当系统的
1
2
2
5 4
4 3
3 2
5 4
2
5 4
4 3
3 2
5 5
1
NO
YES
【分析】(首先想吐槽一句,这游戏情景不是炉石吗??!)。看到这道题,n<=10,想到用暴力dfs,把我方所有有可能出场顺序枚举一遍,再对某一种方案判断是否可行。
一般来说要写个dfs决定所有有可能的出场顺序,但这里可以偷个小懒,可以用STL库中的next_permutation()函数来实现出场顺序的全排列,具体实现过程为从序列的最小表示开始,依次变大,直到成为最大表示结束。如序列(1,2,3),从(1,2,3)变为(1,3,2)逐渐增大直到(3,2,1)结束。还有一个prev_permutation()函数,功能正好相反。
其他具体细节见代码。
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define mst(a,b) memset((a),(b),sizeof(a))#define f(i,a,b) for(int i=(a);i<=(b);++i)#define rush() int T;scanf("%d",&T);while(T--)typedef long long ll;const int maxn= 15;const ll mod = 1e9+7;const int INF = 0x3f3f3f3f;const double eps = 1e-6;int order[maxn]= {0,1,2,3,4,5,6,7,8,9}; //出场顺序int blood1[maxn],blood2[maxn];int cost1[maxn],cost2[maxn];int temp1[maxn],temp2[maxn];int n,flag;bool judge(int *a){ /*for(int i=0;i<n;i++) { printf("%d ",a[i]); } puts("");*/ for(int i=0; i<n; i++) //由于每次都要改变blood的值,所以要注意初始化 { blood1[i]=temp1[i]; blood2[i]=temp2[i]; } int i=0,j=0; while(i<n&&j<n) { int xx=min(blood1[i]/cost2[order[j]],blood2[order[j]]/cost1[i]); //优化,减少循环次数 blood1[i]-=(cost2[order[j]]*xx); blood2[order[j]]-=(cost1[i]*xx); while(blood1[i]>0&&blood2[order[j]]>0) { blood1[i]-=cost2[order[j]]; blood2[order[j]]-=cost1[i]; } if(blood1[i]<=0) { i++; } if(blood2[order[j]]<=0) { j++; } } if(i==n&&j<n) flag=1; //系统的怪兽死完了,但我方还有怪兽存活 return flag;}int main(){ rush() { scanf("%d",&n); for(int i=0; i<n; i++) { scanf("%d%d",&blood1[i],&cost1[i]); temp1[i]=blood1[i]; } for(int i=0; i<n; i++) { scanf("%d%d",&blood2[i],&cost2[i]); temp2[i]=blood2[i]; } flag=0; do { if(judge(order)) { flag=1; break; } } while(next_permutation(order,order+n)); //全排列 if(flag) puts("YES"); else puts("NO"); } return 0;}
第八题:
调和序列
时间限制: 1000ms 内存限制: 128M
给定一个长度为
定义:
第一行一个整数
对于每组数据,第一行输入两个整数
接下来一行是
231
,接下来
每组数据对于每个询问输出一行,若
1
1
5 2
2 5 3 4 1
2 4
2 1
1
-1
3
【分析】先用vector容器预处理一下即可,注意过程中的优化。
#include <cstdio>#include <vector>#include <cstring>#include <algorithm>using namespace std;#define mst(a,b) memset((a),(b),sizeof(a))#define f(i,a,b) for(int i=(a);i<=(b);++i)#define rush() int T;scanf("%d",&T);while(T--)typedef long long ll;const int maxn= 20005;const ll mod = 1e9+7;const int INF = 0x3f3f3f3f;const double eps = 1e-6;vector<int>vec[maxn];int a[maxn];bool flag[maxn];int n,m;void init(){ for(int i=1;i<n;i++) { for(int j=0;j<n;j+=i) vec[i].push_back(a[j]); }}int main(){ rush() { mst(flag,0); scanf("%d%d",&n,&m); for(int i=0;i<n;i++) { scanf("%d",&a[i]); vec[i].clear(); } init(); int k,s; for(int i=0;i<m;i++) { scanf("%d%d",&k,&s); if(k>=n) { if(s==1) printf("%d\n",a[0]); else puts("-1"); continue; } if(vec[k].size()<s) //优化1 { puts("-1"); continue; } if(flag[k]==0) //优化2 { sort(vec[k].begin(),vec[k].end()); flag[k]=1; } printf("%d\n",vec[k][vec[k].size()-s]); } } return 0;}
第九题:
丢史蒂芬妮
时间限制: 1000ms 内存限制: 128M
有一天,空和白很无聊,决定玩盛大游戏,考虑到两个人玩,他们随便掏了一个游戏出来:在一个
白说,这是一个垃圾游戏!我们每次把史蒂芬妮丢素数个位置吧!(换句话说,每次丢
我们都知道,空和白都很聪明,不管哪方存在一个可以必胜的最优策略,都会按照最优策略保证胜利。
玩了一局,空已经知道了这个游戏的套路,现在他决定考考你,对于给定的
第一行有一个T表示数组组数,
从第二行开始,每行为棋盘大小,
对于每组数据,按题目要求输出。
1
4
1 1
2 2
10 10
30 30
1
Shiro
Shiro
Shiro
Sora
【分析】这个博弈题其实就是必胜态与必败态的转化,比赛的时候没去仔细想。。。其实知道两句话即可:
- 如果一个点能够走到必败点,那它就是必胜点
- 如果一个点走不到必败点,只能走到必胜点,这个点就是必败点。
然后从终点开始推回起点,得到每个点是必胜态还是必胜态。但开始在线查询,一组数据推一遍结果超时,再看了下测试数据组数,非常大,而且如果每次递推的话会有很多冗余的地方,改为先预处理再离线查询就16ms AC了。
#include <cstdio>#include <vector>#include <cstring>#include <algorithm>using namespace std;#define mst(a,b) memset((a),(b),sizeof(a))#define f(i,a,b) for(int i=(a);i<=(b);++i)#define rush() int T;scanf("%d",&T);while(T--)typedef long long ll;const int maxn= 500;const ll mod = 1e9+7;const int INF = 0x3f3f3f3f;const double eps = 1e-6;int prime[maxn+5]= {0};int num_prime=0;bool isprime[maxn+5]= {1,1};int vis[maxn+5][maxn+5];void init(){ for(int i=2; i<maxn+5; i++) { if(!isprime[i]) prime[num_prime++]=i; for(int j=0; j<num_prime&&i*prime[j]<maxn+5; j++) { isprime[i*prime[j]]=1; if(i%prime[j]==0) break; } } mst(vis,0); //1:必胜 2:必败 vis[1][1]=2; for(int i=1; i<=maxn; i++) { for(int j=1; j<=maxn; j++) { if(vis[i][j]==0) { vis[i][j]=2; } if(vis[i][j]==2) { for(int k=0; ; k++) { if(i+prime[k]>maxn&&j+prime[k]>maxn) break; if(i+prime[k]<=maxn) { vis[i+prime[k]][j]=1; } if(j+prime[k]<=maxn) { vis[i][j+prime[k]]=1; } if(i+prime[k]<=maxn&&j+prime[k]<=maxn) { vis[i+prime[k]][j+prime[k]]=1; } } } } }}int main(){ init(); int n,m; rush() { scanf("%d%d",&n,&m); if(vis[n][m]==1) puts("Sora"); else puts("Shiro"); } return 0;}
第十题:
膜一下将带给你好运
时间限制: 1000ms 内存限制: 128M
欧拉函数
定义
其中
第一行一个整数
每组数据输出一行,表示函数值
1
2
1068
972
1
293824
222698
【分析】由于一般要处理多个数的欧拉函数值,数量级只能到10^6数量级,所以题目所给的1e8显然无法通过这种方法能到欧拉函数值。正确做法是先预处理出一定范围内的欧拉函数值,然后再根据杜教筛求解,在计算结果时可以用分块加速。
由于对这方面见解不深刻,先给出代码。
#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>using namespace std;#define mst(a,b) memset((a),(b),sizeof(a))#define f(i,a,b) for(int i=(a);i<=(b);++i)#define rush() int T;scanf("%d",&T);while(T--)typedef long long ll;const int maxn= 5000005;const ll mod = 1e9+7;const int INF = 0x3f3f3f3f;const double eps = 1e-6;int res[maxn]= {0};ll sum[maxn]= {0};void euler(){ res[1]=1; for(int i=2; i<maxn; i++) { if(!res[i]) { for(int j=i; j<maxn; j+=i) { if(!res[j]) res[j]=j; res[j]=res[j]/i*(i-1); } } } for(int i=1; i<maxn; i++) { sum[i]=(sum[i-1]+res[i])%mod; }}ll fun(ll x){ if(x<maxn)return sum[x]; ll ans=0; int l,r; for(int i=2; i<=x; i=r+1) { l=i; r=x/(x/i); ans=(ans+fun(x/i)*(r-l+1)%mod)%mod; } ll temp=(x*(x+1)/2-ans+mod)%mod; return temp;}int main(){ euler(); ll n; rush() { scanf("%lld",&n); ll ans=0; ll gap=n-233; ll l,r; for(int i=233; i<=gap; i=r+1) { l=i; r=min(n/(n/i),gap); ll temp=(fun(r)-fun(l-1)+mod)%mod; temp=(temp*(n/i))%mod; ans=(ans+temp)%mod; } printf("%lld\n",ans); } return 0;}
第十一题:
购买装备
时间限制: 1000ms 内存限制: 128M
最近盛大的一款游戏传奇世界极其火爆。游戏玩家John,想购买游戏中的装备。已知游戏的商店里有
输入测试组数
对于每组数据,输出两个数字,第一个数字代表John最多可以购买的装备数,第二个数代表在John购买最多件装备的前提下,所购买的装备当中拥有最小属性值的装备的最大属性值(输入数据保证至少可以购买一件装备)
1
1
2 4
3 2
2 3
1
1 3
【分析】我们可以用贪心的方法先算出可以购买装备的最大数量,然后再去二分属性值,得到在装备购买数量最大的情况下属性值的最大值。
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define mst(a,b) memset((a),(b),sizeof(a))#define f(i,a,b) for(int i=(a);i<=(b);++i)#define rush() int T;scanf("%d",&T);while(T--)typedef long long ll;const int maxn= 100005;const ll mod = 1e9+7;const int INF = 0x3f3f3f3f;const double eps = 1e-6;struct node{ int w,cost;}a[maxn];int n,m;int num;bool cmp(const node &a,const node &b){ if(a.cost==b.cost) return a.w>b.w; return a.cost<b.cost;}int judge(int x){ int sum=0; int Count=0; for(int i=0;i<n;i++) { if(a[i].w>=x) { Count++; sum+=a[i].cost; } if(Count==num) break; } if(Count!=num) return 0; if(sum<=m) return 1; return 0;}int main(){ rush() { scanf("%d%d",&n,&m); int temp=m; int Min=INF; int Max=0; for(int i=0;i<n;i++) { scanf("%d%d",&a[i].w,&a[i].cost); Min=min(a[i].w,Min); Max=max(a[i].w,Max); } sort(a,a+n,cmp); num=0; while(m>=a[num].cost) //得到可以购买装备的最大数目 { m-=a[num].cost; num++; if(num==n) break; } m=temp; int l=Min,r=Max; int ans; while(l<=r) //二分属性值区间 { int mid=(l+r)/2; if(judge(mid)) //判断是否存在这个属性值,能取到num件装备,且总花费小于总的金币数 { ans=mid; l=mid+1; } else r=mid-1; } printf("%d %d\n",num,ans); } return 0;}
第十三题:
风力观测
时间限制: 1000ms 内存限制: 128M
小Y正在观测y地区的风力情况,他在一条直线上依此设定了
你简化了这个问题,将问题分为两种查询:
1.对观测点
2.查询观测点
第一行有一个整数
接着有
第二行有
接着有
1 L R X:表示对
2 A:表示查询
对每次询问2,输出一个数字表示风力值并换行。
1
1
5 6
1 -1 2 3 -3
1 1 5 1
2 1
2 2
1 2 4 -5
2 2
2 3
1
2
1
5
3
【分析】这题应该是线段树题目里有点难度的题吧。我们先初始化线段树上每个点的的值为0,然后进行更新操作,并用Max[i]和Min[i]分别表示i这个结点的历史最大值和历史最小值。每次查询i节点时的结果ans即为:
ans=max(abs(a[i]+Min[i]),abs(a[i]+Max[i])).
值得注意的是,每次pushdown时需要更新以下值(当前节点为x,其父节点为fa)
Min[x]=min(Min[x],lazy[x]+Min[fa])
Max[x]=min(Max[x],lazy[x]+Max[fa])
lazy[x]+=lazy[fa]
同时要把关于父节点的数据清零(很好理解,因为已经传下去了嘛)。
#include <cstdio>#include <cmath>#include <iostream>#include <queue>#include <cstring>#include <algorithm>using namespace std;#define mst(a,b) memset((a),(b),sizeof(a))#define f(i,a,b) for(int i=(a);i<=(b);++i)#define rush() int T;scanf("%d",&T);while(T--)#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1typedef long long ll;typedef pair<int,int>P;const int maxn= 100005;const ll mod = 1e9+7;const int INF = 0x3f3f3f3f;const double eps = 1e-6;int Max[maxn<<2],Min[maxn<<2],lazy[maxn<<2];int a[maxn];void pushdown(int rt){ Max[rt<<1]=max(Max[rt<<1],lazy[rt<<1]+Max[rt]); Min[rt<<1]=min(Min[rt<<1],lazy[rt<<1]+Min[rt]); Max[rt<<1|1]=max(Max[rt<<1|1],lazy[rt<<1|1]+Max[rt]); Min[rt<<1|1]=min(Min[rt<<1|1],lazy[rt<<1|1]+Min[rt]); lazy[rt<<1]+=lazy[rt]; lazy[rt<<1|1]+=lazy[rt]; Min[rt]=Max[rt]=lazy[rt]=0;}/*void build(int l,int r,int rt){ lazy[rt]=Max[rt]=Min[rt]=0; if(l==r) return; int m=(l+r)/2; build(lson); build(rson);}*/void update(int x,int y,int val,int l,int r,int rt){ if(x<=l&&r<=y) { lazy[rt]+=val; Max[rt]=max(Max[rt],lazy[rt]); Min[rt]=min(Min[rt],lazy[rt]); return; } if(Max[rt]||Min[rt]||lazy[rt]) pushdown(rt); int m=(l+r)/2; if(x<=m) update(x,y,val,lson); if(y>m) update(x,y,val,rson);}P query(int pos,int l,int r,int rt){ if(l==r) return P(Max[rt],Min[rt]); if(Max[rt]||Min[rt]||lazy[rt]) pushdown(rt); int m=(l+r)/2; if(pos<=m) return query(pos,lson); return query(pos,rson);}int main(){ int n,q; rush() { scanf("%d%d",&n,&q); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } //build(1,n,1); mst(lazy,0); mst(Max,0); mst(Min,0); int order,l,r,x; for(int i=0;i<q;i++) { scanf("%d",&order); if(order==1) { scanf("%d%d%d",&l,&r,&x); update(l,r,x,1,n,1); } else if(order==2) { scanf("%d",&x); P ans=query(x,1,n,1); printf("%d\n",max(abs(a[x]+ans.first),abs(a[x]+ans.second))); } } } return 0;}
第十四题:
密码破解
时间限制: 1000ms 内存限制: 128M
近日来勒索病毒的事件频繁发生,小Y对它的加密原理非常感兴趣,研究了一番相关知识之后,他就来给你看他的加密程序,并给你一段密文,和你炫耀说就算把程序给你看你也破解不出来。
你扫了一眼代码发现加密的公式为
进一步分析发现
作为一个计算机高手,你早就对加密算法烂熟于心,一眼就看出这个程序的算法和原理,找到了破解的方法,发现小Y疏忽在与给了你一个不够大的
你知道解密的公式与加密对称,为
但是你仍然无法心算解出这个
第一行有一个整数
接着有
第一行有四个数
第二行是需要解密的数字序列
保证
对于每组数据输出一行,表示解密后的数字序列,数字之间以空格隔开。
1
1
5 19 29 3
335 440 514
1
65 67 77
对于样例,存在d=101使得解密公式成立。
注意m和ai的大小可能超过int的范围
【分析】这题之前一模一样做过,联想到了然而忘记了做法,该反思。具体解析见这里Problem G: L先生的回信2
主要思路是d*e==(恒等于)1mod(φ(m)),求逆元再用快速幂。
另外由于这里p,q互质,所以直接可以得到其phi值为(p-1)*(q-1)
这道题一开始就求了下逆元,然后用快速幂取余模板,但一直WA,怎么也找不出错误,后来才知道由于快速幂中的mod数可能很大,所以会爆long long,所以在快速幂的过程中套一个快速乘即可。
#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>using namespace std;#define mst(a,b) memset((a),(b),sizeof(a))#define f(i,a,b) for(int i=(a);i<=(b);++i)#define rush() int T;scanf("%d",&T);while(T--)typedef long long ll;const int maxn= 1005;//const ll mod = 1e9+7;const int INF = 0x3f3f3f3f;const double eps = 1e-6;ll ans[maxn];ll exgcd(ll a,ll b,ll &x,ll &y){ if(b == 0) { x = 1,y = 0; return a; } ll d = exgcd(b,a%b,x,y); ll t = x; x = y,y = t - (a/b)*y; return d;}ll get_inv(ll a,ll Mod){ ll x,y; exgcd(a,Mod,x,y); return (x%Mod+Mod)%Mod;}ll fun(ll a,ll b,ll c) { a%=c,b%=c; ll sum=0; while(b) { if(b&1) sum=(sum+a)%c; a=a*2%c; b>>=1; } return sum;}ll fast_mod(ll a,ll b,ll c){ ll ans=1; a%=c; while(b) { if(b&1) ans=fun(ans,a,c); b>>=1; a=fun(a,a,c); } return ans;}int main(){ ll p,q,e; ll n; rush() { scanf("%lld%lld%lld%lld",&e,&p,&q,&n); ll m=p*q; ll temp=(p-1)*(q-1); //φ(m) ll d=get_inv(e,temp); ll num; for(ll i=0; i<n; i++) { scanf("%lld",&num); ans[i]=fast_mod(num,d,m); } for(ll i=0; i<n-1; i++) { printf("%lld ",ans[i]); } printf("%lld\n",ans[n-1]); } return 0;}
- “盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛
- “盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛-O题
- “盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛:I. 丢史蒂芬妮
- “盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛-神无月排位赛
- “盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛-专题
- 购买装备(“盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛
- 黑白图像直方图“盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛
- I Love ces“盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛
- A序列“盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛
- 战斗“盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛
- 调和序列“盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛
- 丢史蒂芬妮“盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛
- SHU-“盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛-I-丢史蒂芬妮
- “盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛
- 添加好友“盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛(重现赛)
- “盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛 M SHUOJ 422 风力观测
- (补题心路)——“盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛
- 字符串进制转换“盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛
- 仿射变换和SURF特征点匹配
- Wins系统带选项复制命令robocopy的操作方法介绍
- c# 发送qq邮箱本地正常 布置到服务器上后出现的异常
- 求最长上升子序列
- 【分析】Ceph系统架构
- “盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛
- 关于表达式中除数为0的容错机制的处理
- 把数组排成最小的数
- 剑指Offer----跳台阶
- Js-web-API(一)
- 实现自定义标签
- poll服务器
- 面向对象(上)
- leetcode 72. Edit Distance