洛谷11月月赛round.2
P3414 SAC#1 - 组合数
题目背景
本题由世界上最蒟蒻最辣鸡最撒比的SOL提供。
寂月城网站是完美信息教室的官网。地址:http://191.101.11.174/mgzd 。
题目描述
辣鸡蒟蒻SOL是一个傻逼,他居然觉得数很萌!
今天他萌上了组合数。现在他很想知道simga(C(n,i))是多少;其中C是组合数(即C(n,i)表示n个物品无顺序选取i个的方案数),i取从0到n所有偶数。
由于答案可能很大,请输出答案对6662333的余数。
输入输出格式
输入格式:
输入仅包含一个整数n。
输出格式:
输出一个整数,即为答案。
输入输出样例
3
4
说明
对于20%的数据,n <= 20;
对于50%的数据,n <= 1000;
对于100%的数据,n <= 1 000 000 000 000 000 000 (10^18)
2的n-1次方
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; typedef long long ll; const ll MOD=6662333; ll n; ll powMod(ll a,ll b){ ll ans=1; for(;b;b>>=1,a=(a*a)%MOD) if(b&1) ans=(ans*a)%MOD; return ans; } int main(){ scanf("%lld",&n); printf("%lld",powMod(2,n-1)); }
P3413 SAC#1 - 萌数
题目背景
本题由世界上最蒟蒻最辣鸡最撒比的SOL提供。
寂月城网站是完美信息教室的官网。地址:http://191.101.11.174/mgzd 。
题目描述
辣鸡蒟蒻SOL是一个傻逼,他居然觉得数很萌!
好在在他眼里,并不是所有数都是萌的。只有满足“存在长度至少为2的回文子串”的数是萌的——也就是说,101是萌的,因为101本身就是一个回文数;110是萌的,因为包含回文子串11;但是102不是萌的,1201也不是萌的。
现在SOL想知道从l到r的所有整数中有多少个萌数。
由于答案可能很大,所以只需要输出答案对1000000007(10^9+7)的余数。
输入输出格式
输入格式:
输入包含仅1行,包含两个整数:l、r。
输出格式:
输出仅1行,包含一个整数,即为答案。
输入输出样例
1 100
10
100 1000
253
说明
记n为r在10进制下的位数。
对于10%的数据,n <= 3。
对于30%的数据,n <= 6。
对于60%的数据,n <= 9。
对于全部的数据,n <= 1000,l < r。
在出题人标程的帮助下终于A掉了
数位DP
逆向思维,求不含回文的数
f[i][j][k]表示到i位i为j i-1为k的不含回文的数的个数
很简单的递推,我用了个sum[i][j]来优化
天际线的处理要注意,一开始就是因为打错了哪里
ans要用f更新,而不是sum,否则还是有可能产生回文,天际线跟其他的不一样i之前还有数
PS:高精度-1挺坑的
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <map> using namespace std; const int N=1005,INF=1e9+5,MOD=1e9+7; typedef long long ll; char l[N],r[N]; int n; ll f[N][11][11],sum[N][N]; void dp(int n){ for(int i=0;i<=9;i++){ for(int j=0;j<=9;j++) if(i!=j) f[2][i][j]=1; sum[2][i]=9; sum[1][i]=1; } for(int i=3;i<=n;i++) for(int j=0;j<=9;j++){ for(int k=0;k<=9;k++) if(j!=k){ for(int z=0;z<=9;z++) if(j!=z&&k!=z) f[i][j][k]=(f[i][j][k]+f[i-1][k][z])%MOD; sum[i][j]=(sum[i][j]+f[i][j][k]); } } } void dec(char s[],int &n){ s[n]--;int tn=n; while(s[n]<'0') s[n]='9',s[--n]--; if(s[1]=='0'){ tn--; for(int i=1;i<=tn;i++) s[i]=s[i+1]; } n=tn; } ll sol(char s[],int n){ ll ans=0,a[N]; ll tot=0; if(n==1||n==0) return 0; for(int i=1;i<=n;i++) a[i]=s[n-i+1]-'0',tot=(tot*10+s[i]-'0')%MOD; a[n+1]=-1; for(int i=1;i<=n-1;i++) for(int j=1;j<=9;j++) ans=(ans+sum[i][j])%MOD; for(int j=1;j<a[n];j++) ans=(ans+sum[n][j])%MOD; int flag=0; for(int i=n-1;i>=1;i--){ for(int j=0;j<a[i];j++) if(j!=a[i+1]&&j!=a[i+2]) ans=(ans+f[i+1][a[i+1]][j])%MOD;//!!!not sum[i][j] cause huiwen if(a[i]==a[i+1]||a[i]==a[i+2]) {flag=1;break;} } if(!flag) ans++; return (tot-ans+MOD)%MOD; } int main(){ scanf("%s%s",l+1,r+1); int len1=strlen(l+1),len2=strlen(r+1); dp(len2); dec(l,len1); printf("%lld",(sol(r,len2)-sol(l,len1)+MOD)%MOD); }